Why “using namespace std” is considered bad practice
The statement using namespace std is generally considered bad practice. The alternative to this statement is to specify the namespace to which the identifier belongs using the scope operator(::) each time we declare a type.
Although the statement saves us from typing std:: whenever we wish to access a class or type defined in the std namespace, it imports the entirety of the std namespace into the current namespace of the program. Let us take a few examples to understand why this might not be such a good thing
Let us say we wish to use the cout from the std namespace. So we write
Now at a later stage of development, we wish to use another version of cout that is custom implemented in some library called “foo” (for example)
Notice now there is an ambiguity, to which library does cout point to? The compiler may detect this and not compile the program. In the worst case, the program may still compile but call the wrong function, since we never specified to which namespace the identifier belonged.
Namespaces were introduced into C++ to resolve identifier name conflicts. This ensured that two objects can have the same name and yet be treated differently if they belonged to different namespaces. Notice how the exact opposite has occurred in this example. Instead of resolving a name conflict, we actually create a naming conflict.
When we import a namespace we are essentially pulling all type definitions into the current scope. The std namespace is huge. It has hundreds of predefined identifiers, so it is possible that a developer may overlook the fact there is another definition of their intended object in the std library. Unaware of this they may proceed to specify their own implementation and expect it to be used in later parts of the program. Thus there would exist two definitions for the same type in the current namespace. This is not allowed in C++, and even if the program compiles there is no way of knowing which definition is being used where.
The solution to the problem is to explicitly specify to which namespace our identifier belongs to using the scope operator (::). Thus one possible solution to the above example can be
But having to type std:: every time we define a type is tedious. It also makes our code look hairier with lots of type definitions and makes it difficult to read the code. Consider for example the code for getting the current time in the program
The source code that is littered with complicated and long type definitions is not very easy to read. This is something developers seek to avoid since code maintainability is chiefly important to them.
There are a few ways to resolve this dilemma i.e specify exact namespace without littering code with std keywords.
Consider using typedefs
typedefs save us from writing long type definitions. In our example 1, we could solve the problem using two typedefs one for std library and another for foo
Instead of importing entire namespaces, import a truncated namespace
In example 2 we could have imported only the chrono namespace under std.
We can also use the statement for importing a single identifier. To import only std::cout we could use
If you still import entire namespaces, try to do so inside functions or limited scope and not in global scope.
Use the “using namespace std” statement inside function definitions or class, struct definitions. In doing so the namespace definitions get imported into a local scope, and we at least know where possible errors may originate if they do arise.
We have discussed alternative methods for accessing an identifier from a namespace. In all cases avoid importing entire namespaces into the source code.
While good coding practices may take some time to learn and develop, they generally pay out in the long run. Writing clean, unambiguous and robust error-free code should be the intent of any programming developer.