Module 1 · From C to Just-Enough C++
std::, Namespaces and the Headers You Will Actually Include
In this lesson
- Explain what a namespace is, write two of your own, and reach a name inside one with
::. - Choose between
std::, a using-declaration andusing namespace std;, and say why the last one never goes in a header. - Name the header for every standard name this track uses, and say why
<bits/stdc++.h>works only on GCC.
Bob's contest program starts with #include <bits/stdc++.h>, and on the Playground it compiles and passes. Maria copies it to her Mac, whose compiler is clang with its own library, and it stops at the first line: fatal error: 'bits/stdc++.h' file not found. Nothing in the program is wrong, and still one compiler takes it and another refuses. To see why, you need two ideas: where a standard name lives, and which file brings it into your program. This lesson gives you both, and a table to keep.
A namespace is a named box of names
In C every function name is global, so two libraries cannot both have a sort. C libraries dodge this with a prefix on every name, such as sqlite3_open. C++ has a better tool. A namespace is a named box of names: two boxes can each hold a sort, and they never clash.
Making a namespace, and reaching into it
namespace box_name {
declarations: functions, variables, constants
}
box_name::name
namespaceopens a box;box_nameis the box's own name.- Everything declared between the braces lives inside the box.
::, the scope operator, looks inside a box:box_name::namemeans "thenamein that box".
Here are two functions called sort in one program, one in a shop's box and one in a school's.
#include <iostream>
namespace shop {
void sort()
{
std::cout << "shop::sort puts prices cheapest first\n";
}
}
namespace school {
void sort()
{
std::cout << "school::sort puts marks highest first\n";
}
}
int main()
{
shop::sort();
school::sort();
return 0;
}
shop::sort puts prices cheapest first
school::sort puts marks highest first
The compiler never asks which sort you mean, because each call names its box. main itself lives in no box you made. It sits in the global namespace, the outermost box of every program, where all of C's names live too.
So a namespace lets two pieces of code use the same name, and box::name says which one you mean.
std:: and three ways not to type it
The C++ standard library keeps every one of its names in one namespace, std. That is why lesson 01 wrote std::cout: the cout in the std box. Typing std:: fifty times a program is tiring, so C++ has three ways to skip it.
A using-declaration lets one name in: using std::cout;. A using-directive lets the whole box in: using namespace std;. Each one works from the line it is written on to the end of the block that holds it. Written at the top of the file, that is the rest of the file; written inside a function, it is that function only.
#include <iostream>
#include <string>
using std::cout;
int main()
{
using std::cin;
std::string title;
int pages = 0;
cin >> title >> pages;
cout << title << " has " << pages << " pages\n";
return 0;
}
Matilda has 240 pages
That output is for the input Matilda 240. cout needs no std:: anywhere below its using-declaration, and cin needs none inside main. std::string was never let in, so it keeps its std::.
| You write | Where | What you can then write without std:: |
|---|---|---|
std::cout | at every use | nothing; you name the box each time |
using std::cout; | top of the file | cout, for the rest of the file |
using std::cin; | inside a function | cin, inside that function only |
using namespace std; | top of the file | every name in std, for the rest of the file |
So cout after any of these is still std::cout. What changes is how many names you let out of the box, and how far.
What using namespace std costs, and the one rule
Lesson 01 said that using namespace std; pours hundreds of names into your program, and that one of yours can collide with one of them. Here is the collision. Kenji counts the laps he has left in a global variable named left.
#include <iostream>
using namespace std;
int left = 3;
int main()
{
cout << left << " laps left\n";
return 0;
}
GCC 12 refuses it at the Playground's command line and at -Wall -Wextra alike: error: reference to 'left' is ambiguous. The notes name the two candidates, Kenji's 'int left' and 'std::ios_base& std::left(ios_base&)'. std::left is a real name from <iostream>, a setting that lines output up on the left. Kenji never asked for it; the using-directive let it out, and now there are two global lefts.
Move the variable inside main, and the same program compiles and prints 3 laps left. A name declared inside a function hides the ones outside it, the box's included. So the clash bites names at the top of a file, which is where contest programs keep their big arrays and counters.
That is the cost in a single file. In a header, a file that other files include, the cost spreads. #include pastes the header's text into the file that includes it, as in C. So a using-directive inside a header lands in every one of those files. Their authors never wrote it, and their names start colliding.
So this track has one rule, and one habit. The rule: using namespace std; never goes in a header. The habit: a short one-file contest program may use it, but this module, and every project lesson in the track, writes std:: on every standard name.
The header table: which file brings which name
A namespace says what a name is called. A header says where it is declared, and you must #include it before the name exists in your program. Every name in this track comes from one of the headers below. The table is worth keeping open beside your first STL programs.
| Header | What it gives you | Taught in |
|---|---|---|
<iostream> | std::cin, std::cout, std::cerr | lessons 01 and 02 |
<string> | std::string, std::getline, std::to_string | Module 3 |
<sstream> | std::istringstream, reading numbers out of a string | pointed at in lesson 02, Module 3 |
<utility> | std::pair, std::swap, std::move | lessons 05 and 06 |
<tuple> | std::tuple, std::get, std::tie | lesson 06 |
<vector> | std::vector | Module 2 |
<array> | std::array | Module 4 |
<deque> | std::deque | Module 4 |
<list> | std::list | Module 5 |
<forward_list> | std::forward_list | Module 5 |
<stack> | std::stack | Module 6 |
<queue> | std::queue, and also std::priority_queue | Module 6, Module 7 |
<set> | std::set, std::multiset | Module 8 |
<map> | std::map, std::multimap | Module 9 |
<unordered_set> | std::unordered_set | Module 10 |
<unordered_map> | std::unordered_map | Module 10 |
<iterator> | std::next, std::prev, std::distance | Module 11 |
<functional> | std::greater, the "larger first" order | Module 7, Module 12 |
<algorithm> | std::sort, std::max, std::min, std::reverse, std::count, std::lower_bound | lesson 05, Module 12, Module 13 |
<numeric> | std::accumulate, std::iota, std::gcd | Module 14 |
<bitset> | std::bitset | Module 15 |
<chrono> | clocks for timing a program | used in lessons 02 to 04 to measure |
Two rows surprise people. std::priority_queue has no header of its own; it lives in <queue>. And std::swap is in <utility>, while its neighbours std::max and std::min are in <algorithm>. So when GCC says a name is not a member of 'std', look its header up here first.
Include exactly what you use
Here is a fact found while writing lesson 05. This program has no <algorithm>, and GCC 12 compiles it anyway.
#include <iostream>
int main()
{
std::cout << std::max(3, 7) << '\n';
return 0;
}
7
It works by luck. GCC's library, libstdc++, builds <iostream> out of other headers. A few files down that chain it includes <string>, and <string> includes bits/stl_algobase.h, the file where std::max is defined. Compiler Explorer's include list (GCC's -H option) shows every step of it.
Other compilers come with other libraries, built in other ways. On Compiler Explorer we compiled three one-header programs, each including only <iostream>, on three toolchains.
With only <iostream>, a call to | GCC 12, libstdc++ | clang 15, libc++ | MSVC, Microsoft's library |
|---|---|---|---|
std::max | compiles | compiles | compiles |
std::getline | compiles | compiles | error C2039: 'getline': is not a member of 'std' |
std::sort | error: 'sort' is not a member of 'std'; did you mean 'qsort'? | compiles | error C2039: 'sort': is not a member of 'std' |
The GCC column is the Playground's command line, -O2 -std=c++17. The clang column is clang 15 with -stdlib=libc++, its own library, and the MSVC column is "x64 msvc v19.latest" with /std:c++17. Each library drags in a different set of extras, and none of them promises to keep doing it. So a program that leans on an extra is right on one machine and broken on the next.
The fix costs one line per header. Include every header whose names you use, even when the program compiles without it. Then it compiles on any standard library, today and after the next library update. So the safe answer is never "it compiled on mine", but "every name I use has its header at the top".
bits/stdc++.h: every header at once, on GCC only
<bits/stdc++.h> is a file inside GCC's library that includes every standard header in one go. Its own comment calls it "an implementation file for a precompiled header", a helper for GCC's build speed. It is not part of the C++ standard. Contest programmers love it, because one line replaces a dozen, and the Playground and many contest judges compile with GCC.
#include <bits/stdc++.h>
int main()
{
std::cout << "hello\n";
return 0;
}
hello
That is GCC 12's output. Other toolchains do not have the file at all. On Compiler Explorer, clang 15 with libc++, the library a Mac uses by default, stops at line 1: fatal error: 'bits/stdc++.h' file not found. MSVC stops there too: fatal error C1083: Cannot open include file: 'bits/stdc++.h': No such file or directory. That is Bob and Maria's story from the top of this lesson.
It also costs compile time, because the compiler reads every header, used or not. We built the hello program twice, once with <iostream> and once with <bits/stdc++.h>, one run each.
| Where, and the command | With <iostream> | With <bits/stdc++.h> |
|---|---|---|
This lesson's machine, GCC 14.2 (MinGW), g++ -std=c++17, wall-clock time | 1.39 s | 4.76 s |
Compiler Explorer, GCC 12.2, -O2 -std=c++17, its reported build time | 376 ms | 1130 ms |
Compiler Explorer, GCC 12.2, lines after the preprocessor (-E -P) | 22,382 | 92,295 |
On both machines the one line made a five-line program build at least three times slower. Three later runs on Compiler Explorer gave 289 to 378 ms against 1,863 to 2,888 ms. The local runs came after one warm-up build of each, so the disk was not the difference. In a contest that is a cost you can afford; in a project with hundreds of files, every file pays it.
So the track's rule is simple. <bits/stdc++.h> is allowed in a contest program, and we name it as GCC-only every time it appears. It never appears in a project lesson, because a project must build on every compiler its team uses.
A namespace can hold variables too. Alice tracks stock for a bookshop and a library, and both counts are called stock.
#include <iostream>
namespace bookshop {
int stock = 0;
}
namespace library {
int stock = 0;
}
int main()
{
bookshop::stock = 12;
library::stock = 340;
bookshop::stock = bookshop::stock - 2;
std::cout << "bookshop " << bookshop::stock << ", library " << library::stock << '\n';
return 0;
}
bookshop 10, library 340
Selling two books changed only the bookshop's count. In C the two would need different names, such as bookshop_stock and library_stock; here the box does that job.
Now the shop's and the school's sort do real work, and both are built on a third one, std::sort. It sorts a range of an array into increasing order, and Module 12 teaches it. std::reverse turns a range round.
#include <algorithm>
#include <iostream>
namespace shop {
// Prices go cheapest first.
void sort(int prices[], int n)
{
std::sort(prices, prices + n);
}
}
namespace school {
// Marks go highest first.
void sort(int marks[], int n)
{
std::sort(marks, marks + n);
std::reverse(marks, marks + n);
}
}
void print(const int a[], int n)
{
for (int i = 0; i < n; i++) {
if (i > 0) {
std::cout << ' ';
}
std::cout << a[i];
}
std::cout << '\n';
}
int main()
{
int prices[4] = {300, 120, 450, 200};
int marks[4] = {72, 91, 65, 85};
shop::sort(prices, 4);
school::sort(marks, 4);
print(prices, 4);
print(marks, 4);
return 0;
}
120 200 300 450
91 85 72 65
Look inside shop::sort. A plain sort(prices, prices + n) there finds shop::sort itself, the closest box. GCC 12 then says error: invalid conversion from 'int*' to 'int' [-fpermissive], with a note naming void shop::sort(int*, int). std:: is what sends the call to the standard library.
Amara reads her shop's name and n prices, and prints the count, the total, and the cheapest and dearest price. This is the program a beginner really writes, with exactly the headers it uses.
#include <algorithm>
#include <iostream>
#include <numeric>
#include <string>
const int MAX_N = 100;
int main()
{
std::string shop;
int n = 0;
std::cin >> shop >> n;
if (n == 0) {
std::cout << shop << ": no items\n";
return 0;
}
int prices[MAX_N] = {0};
for (int i = 0; i < n; i++) {
std::cin >> prices[i];
}
std::sort(prices, prices + n);
long long total = std::accumulate(prices, prices + n, 0LL);
std::cout << shop << ": " << n << " items, total " << total << '\n';
std::cout << "cheapest " << prices[0] << ", dearest " << prices[n - 1] << '\n';
return 0;
}
Bookworm: 4 items, total 1070
cheapest 120, dearest 450
That output is for the input Bookworm 4, then 300 120 450 200. Each header pays for itself: <algorithm> for std::sort, <iostream> for std::cin and std::cout, <numeric> for std::accumulate and <string> for std::string. std::accumulate adds up a range starting from 0LL, so the total is a long long (Module 14).
Zara tried Bookworm 0 first. Without the n == 0 check, prices[n - 1] would read prices[-1], outside the array; with it, the program prints Bookworm: no items.
Where this is used
- SQLite. Its C interface has no namespaces to use, so every public name starts with
sqlite3_, as insqlite3_openandsqlite3_exec. A prefix is C's stand-in for a box. - LLVM. The LLVM Coding Standards have a rule titled "Do Not Use 'using namespace std'". They prefer an explicit
std::, and say a using-directive in a header pollutes every file that includes it. - Chromium. Google's browser follows the Google C++ Style Guide, which says not to use using-directives such as
using namespace foo. - GCC's own library.
bits/stdc++.hships with libstdc++, and its comment describes it as an implementation file for a precompiled header. That is why it exists on GCC and on judges that use GCC, and nowhere else.
Common mistakes
1. Leaving out std:: with no using line.
cout << "hello\n";
An error at every command line: error: 'cout' was not declared in this scope; did you mean 'std::cout'?. GCC even names the box. Write std::cout. You will make this one because most code you find online starts with using namespace std;, and you copy the body without that line.
2. One colon instead of two.
std:cout << "hello\n";
The Playground's command line gives the same message as mistake 1. With -Wall -Wextra, GCC 12 adds the clue: warning: label 'std' defined but not used [-Wunused-label]. std: with one colon is a C label, a target for goto, so cout is left bare. You will type it when you are fast, because a double colon is one key pressed twice.
3. Using a name without its header.
#include <iostream>
int main()
{
std::vector<int> v(3);
return 0;
}
An error at every command line: error: 'vector' is not a member of 'std', and a helpful note, 'std::vector' is defined in header '<vector>'; did you forget to '#include <vector>'?. GCC does not always know the header: for std::sort it suggests 'qsort', and for std::accumulate it suggests nothing. So read "is not a member of 'std'" as "a header is missing", and look the name up in the table.
4. Calling your own function without its box.
namespace shop {
void sort()
{
}
}
sort();
An error at every command line: error: 'sort' was not declared in this scope; did you mean 'shop::sort'?. Outside the box, its names need the box's name. Write shop::sort();. You will forget it because inside shop the plain name worked.
Zara makes a spelling list for her class and wants the words in dictionary order. Write the program with exactly the headers it uses: no header it does not need, none missing, and no <bits/stdc++.h>.
Input. A line with n, then n words.
Output. The n words in dictionary order, one per line.
Constraints. 1 <= n <= 100. Each word is 1 to 20 lowercase letters.
Sample. Input 4, then pear apple zebra mango, gives apple, mango, pear and zebra on four lines.
#include <iostream>
// Add the other headers this program uses here, one per line,
// in alphabetical order. Not <bits/stdc++.h>.
const int MAX_N = 100;
int main()
{
int n = 0;
std::cin >> n;
// Read n words into an array of std::string, sort it with
// std::sort, and print the words one per line.
return 0;
}
Not graded on its own. On the Playground it may compile with a header missing, which is this lesson's point, so check every std:: name against the table.
Zara's weather station wants the stronger of two readings: the one further from zero, so -7 beats 5. That is not what std::max means, so she writes her own max in a box of her own, weather, and prints both answers to compare.
Input. Two integers a and b.
Output. Two lines: std::max, one space and the larger of the two; then weather::max, one space and the one further from zero. If both are equally far from zero, weather::max gives a.
Constraints. Each integer is between -100 and 100.
Sample. Input -7 5 gives std::max 5 and weather::max -7 on two lines.
#include <algorithm>
#include <iostream>
namespace weather {
// Return whichever of a and b is further from zero; on a tie, return a.
int max(int a, int b)
{
return a; // replace this line
}
}
int main()
{
int a = 0;
int b = 0;
std::cin >> a >> b;
// Print "std::max " and std::max(a, b) on one line,
// then "weather::max " and weather::max(a, b) on the next.
return 0;
}
Not graded on its own. Zara would test 5 -5 and 0 0 before the sample.
Common doubts
Does
using namespace std;make my program bigger or slower?No. It only changes which names the compiler finds while it reads your code. The program it produces is the same as with
std::written everywhere.Does
<bits/stdc++.h>make the program run slower?No, only compile slower. A declaration nobody uses produces no machine code. On this lesson's machine the two hello programs came out 65,052 and 65,241 bytes, built with GCC 14.2 (MinGW).
Why
std::coutwith two colons, butstd::cin.tiewith a dot?::looks inside a namespace, a box of names..reaches a member of one object, exactly as with a Cstruct.std::cinis an object in thestdbox, andtieis one of its members.Can I add my own function to
std?No. The C++ standard says that adding your own declarations to namespace
stdis undefined behaviour, apart from a few narrow cases. Put your names in a box of your own, asshopandweatherdo.Bob asks: can I still use
scanfandprintf?Yes. In C++ they come from
<cstdio>, the C++ form ofstdio.h, asstd::scanfandstd::printf. Lesson 02's rule still holds: one family of input and output per program.
Key takeaways
- A namespace is a named box of names, and
box::namereaches inside it, soshop::sortandschool::sortnever clash. - The whole standard library lives in
std;using std::cout;lets one name out, andusing namespace std;lets them all out. using namespace std;is fine in a short contest file, never in a header; this module writesstd::on every standard name.- Every standard name comes from a header in the table; include each one you use, because what a header drags in differs between libraries.
<bits/stdc++.h>is GCC's own file: clang with libc++ and MSVC refuse it, and it made a hello program build at least three times slower.
That is the last lesson of this module. Next comes its problem set, ten judged problems that use lessons 01 to 07, and after it Module 2 opens std::vector.
End of lesson 7
Mark it done, and your progress moves with you.
Next: Problems: Just-Enough C++