You should definitely NOT use using namespace in headers for precisely the reason you say, that it can unexpectedly change the meaning of code in any other files that include that header. There's no way to undo a using namespace which is another reason it's so dangerous.
Namespace is a feature added in C++ and is not present in C. A namespace is a declarative region that provides a scope to the identifiers (names of functions, variables or other user-defined data types) inside it. Multiple namespace blocks with the same name are allowed.
std is the namespace and by using :: (after the std) you explicitly using the functions of the namespace std. Now, imagine that you create your own namespace and some of the functions that you have created there have the same name as the functions in std namespace.
Explanation: It is known that “std” (abbreviation for the standard) is a namespace whose members are used in the program. So the members of the “std” namespace are cout, cin, endl, etc. This namespace is present in the iostream. h header file.
From the C++11 Standard (emphasis mine):
D.5 C standard library headers [depr.c.headers]
- For compatibility with the C standard library ...
- Every C header, each of which has a name of the form name.h, behaves as if each name placed in the standard library namespace by the corresponding cname header is placed within the global namespace scope. It is unspecified whether these names are first declared or defined within namespace scope (3.3.6) of the namespace std and are then injected into the global namespace scope by explicit using-declarations (7.3.3).
- Example: The header
<cstdlib>
assuredly provides its declarations and definitions within the namespacestd
. It may also provide these names within the global namespace. The header<stdlib.h>
assuredly provides the same declarations and definitions within the global namespace, much as in the C Standard. It may also provide these names within the namespacestd
.
Using the «name.h» headers is deprecated, they have been identified as candidates for removal from future revisions.
So, I would suggest to include the «cname» headers and to use the declarations and definitions from the std
namespace.
If you have to use the «name.h» headers for some reasons (it's deprecated, see above), I would suggest to use the declarations and definitions from the global namespace.
In other words: prefer
#include <cstdio>
int main() {
std::printf("Hello world\n");
}
over
#include <stdio.h>
int main() {
printf("Hello world\n");
}
<cmeow>
always provides ::std::purr
and may or may not provide ::purr
.
<meow.h>
always provides ::purr
and may or may not provide ::std::purr
.
Use the form that is guaranteed to be provided by the header you include.
No, you're fine either way.
The original intent was that the <___.h>
headers would be the C versions which put everything in the global namespace, and the <c___>
headers would be the C++-ified versions, which place everything in the std
namespace.
In practice, though, the C++ versions also put everything into the global namespace. And there's no clear consensus that using the std::
versions is "the right thing to do".
So basically, use whichever you prefer. The most common is probably to use the C standard library functions in the global namespace (printf
instead of std::printf
), but there's not much reason to consider one "better" than the other.
The only difference there is is that in std::printf()
by adding std::
scope resolution you will secure yourself from someone writing a function with the same name in the future, which would lead to namespace conflict. Both usages will lead to exactly the same OS API calls (you can check it under Linux by running strace your_program
).
I find it very unlikely that someone would name a function like that, as printf()
is one of the most commonly used functions out there. Also, in C++, iostream
s are preffered over calls to cstdio
functions like printf.
From the C++11 standard:
Every C header, each of which has a name of the form name.h, behaves as if each name placed in the standard library namespace by the corresponding cname header is placed within the global namespace scope. It is unspecified whether these names are first declared or defined within namespace scope (3.3.6) of the namespace std and are then injected into the global namespace scope by explicit using-declarations (7.3.3).
So, if you use <cstdio>
, you can be sure, that printf
will be in the namespace std
, and hence not in global namespace.
Using a global namespace creates a conflict of names. This is not C++ way.
Therefore, I'm using <cstdio>
headers and advise you to do so.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With