Why “using namespace std” is considered bad practice

2.6

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 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

Example 1:

#include <iostream>
using namespace std;

cout << " Something to Display";

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)

#include <foo.h>
#include <iostream>
using namespace std;

cout << " Something to display";

Notice how 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 to solution to the above example can be

#include <foo>
#include <iostream>

// Use cout of std library
std::cout << "Something to display";

// Use cout of foo library
foo::cout < "Something to display";

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

Example 2:

#include <chrono>
#include <iostream>

auto start = std::chrono::high_system_clock::now()

// Do Something

auto stop
    = std::chrono::high_peformance_clock::now();
auto duration 
    = std::duration_cast<std::chrono::milliseconds>(stop - start);

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

#include <foo>
#include <iostream>

typedef std::cout cout_std;
typedef foo::cout cout_foo;

cout_std << "Something to write";
cout_foo << "Something to write";


Instead of importing entire namespaces, import a truncated namespace
In example 2 we could have imported only the chrono namespace under std.

#include <chrono>
#include <iostream>

// Import only the chrono namespace under std
using namespace std::chrono;

auto start = high_performance_clock::now();

// Do Something
auto stop = high_performance_clock::now();
auto duration duration_cast<milliseconds>(stop - start);

We can also use the statement for importing a single identifier. To import only std::cout we could use

using namespace std::cout;


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 definations or class, struct definations. In doing so the namespace definations get imported into a local scope, and we atleast know where possible errors may originate if they do arise.

#include <isotream>

// Avoid this
using namespace std;

void foo()
{
    // Inside function
    // Use the import statement inside limited scope
    using namespace std;

    // Proceed with function
}


Conclusion.

We have discussed at alternative methods to 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.


Intern at GeeksForGeeks

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

GATE CS Corner    Company Wise Coding Practice

Recommended Posts:



2.6 Average Difficulty : 2.6/5.0
Based on 5 vote(s)