#045 – The number one mistake beginners make

If you’ve seen this program before in beginner tutorials, you’ll know immediately that the material is out of date

#include <iostream>

using namespace std;

int main()
{
    cout << "Hello world!\\n";
}

What using namespace std; actually does

using namespace std; is an example of a using-directive.using directive tells the compiler to consider every name in the std namespace as a candidate during unqualified name lookup.

This is different from a using declaration such as using std::cout;, which exposes a single method.

The directive is broad and all-encompassing; the declaration is precise.

It’s equivalent to carrying your 37-piece toolbag when you only need a screwdriver. You technically have the tool you need but the other 36 tools are now getting in your way.

Problem 1: Naming collisions

The entire purpose of the std being enclosed in a namespace is to prevent naming collisions.

Suppose you write your own swap function:

#include <iostream>
#include <utility>

using namespace std;

void swap(int& a, int& b){
    a = b;
    b = a; // bug: both end up equal
}

int main(){
    int x = 1, y = 2;
    swap(x, y);
    cout << x << ' ' << y << '\\n';
}

There are now two swap candidates visible without qualification: yours and std::swap. Depending on argument types and overload resolution, the compiler may:

  • Pick the one you did not intend
  • Reject the call as ambiguous.

Remove using namespace std;, and the problem disappears — swap(x, y) calls your function, and std::swap(x, y) calls the Standard Library’s.

Similarly, if you import the std, you can no longer create a custom vector class since it will clash with std::vector.

Whilst this is a simple example, the chance of naming collisions expands with each new revision of the language.

A program that compiled cleanly under C++17 can break under C++20 because a name you used now collides with a new identifier from the Standard Library.

Problem 2: Reader confusion

Code is read more often than it is written.

When a function is called without the scope resolution operator, the reader has to know whether it came from std, from a third-party library, or from your own code:

sort(items.begin(), items.end()); // std::sort? our own sort?

std::sort(items.begin(), items.end()) answers the question immediately. It is clear what scope the function belongs to.

Problem 3: Increased compilation times

using directive in a single small main() is mostly harmless. The same line in a header is a serious mistake — every translation unit that includes the header inherits the pollution.

Additionally, using directives cannot be repealed or replaced.

In Conclusion

Take the extra time to type std::. It costs five characters but it will save you a lot of headache!

When a particular method is used repeatedly a using declaration (using std::cout;) can be used, NOT a using directive.