C++/Functions of the basic structure of a program
Expert: Ralph McArdell - 2/8/2007
QuestionWhen do we use int main() and void main in a program? Why does a C++ program use "using namespace std" while others don't?
Answer1/ The ISO C++ standard states that main may have one of two forms:
int main()
{
/* ... */
}
Or
int main( int argc, char * argv[] )
{
/* ... */
}
The void main() form is a non-standard form specific to older Microsoft compilers (up to VC6 I think).
The standard main function has one other odd thing about it: although a return type is specified you do not need to specify a return value. If no return statement is provided then return 0; is assumed. The reasons go back to the early history of C, which C++ tries to be as compatible with as is sensibly possible. This _only_ applies to main and _no_ other function.
Those older editions of Visual C++ did not allow this if a standard int main() form were used, forcing you to always specify return 0; if you had no other return requirements. So users of Visual C++ tend to use void main() in such cases and think it is a standard form of main. This is especially true if Visual C++ is the only C++ compiler they have ever used.
So in short: always use an int main() form and never use a void main() form. If you wish to ensure your code will compile with older versions of Visual C++ just ensure you include a return statement.
2/ Use of using namespace std directive:
A hosted implementation of ISO standard C++, such as is typically used on desktop PCs and workstations, includes a library of functions and types. Most names in this library are in a namespace called std. This is different to pre-standard C++ libraries in which the names were in the global namespace.
So where in pre-standard C++ you could write:
cout << "Hello world!\n";
Providing you had included <iostream.h> this would compile and run. The cout object name is defined in the global namespace so no additional qualification is needed for the compiler to find it.
In standard C++ the header looses the .h extension, so you have to include <iostream>. Even so the above code will not compile. This is because the cout name is now in the std namespace, and as such has to be qualified with std so the compiler knows where to look for it thus:
std::cout << "Hello world!\n";
As an aid to readability (or maybe write-ability) you can state that a specific name from a namespace when used without qualification in the current scope refers to a name in the given namespace thus:
using std::cout;
This is called a using declaration. As you can see it only specifies one name at a time. It would allow us to write for standard C++:
cout << "Hello world!\n";
As in pre-standard C++, and have the compiler find the item named cout.
A much blunter instrument is the using directive which specifies that all names in a given namespace may be used without qualification in the scope in which it appears. Note that by all names in a namespace I mean all that are known to the compilation in question - that is it does not apply to any that have not been defined or declared whether in the source file directly or in a header included by the source file. An example of a using directive is:
using namespace std;
Its main use is in example code and in converting existing pre-standard C++ code to using standard C++ quickly. If such a project has several millions of lines of code then you do not want to spend several months or more just going through the code prefixing std:: to all instances of C++ library names that are now in the std namespace.
Now you might think why bother with namespaces at all, and why not just always use using namespace std?
The answer to the first part is the reason that standard C++ acquired the namespace facility in the first place. The same names can be used by different people and organisations for similar or different things. This causes name clashes and can make using libraries from different parties difficult or impossible.
As an example let's take the name cout in the example above. This may not seem like a likely candidate for say a variable name in code, and so not obviously a high risk for name clashes. However you might like to try performing a French to English translation of cout using a service such as Google's online translation tools (or even a French English dictionary). The English translation of the French word "cout" it seems is "cost", which is much more likely to be a name in a program quite possibly for a variable. If code using such a variable name also wished to write to the standard console output stream, cout, then there would be a name clash, and the poor program writer would have to think of some longer or less obvious name for their variable (mon_cout maybe <g>).
An additional problem is that the C++ standard library added a lot of names that are common in programs: string, vector, list, stack, queue, sort, find, count, copy, plus, minus, equal, less, greater, min, max etc. Placing such names in the global namespace would likely clash with lots of names in existing programs and libraries, thus breaking lots and lots of existing code. So (nearly) all the standard C++ library names were placed into a namespace called std. So for example the (new) C++ string was fully named std::string thus causing no conflict with existing code using some string type also called string.
The reason not to always use using namespace std is that it is a blunt instrument. It pulls in all the names in the std namespace that your program has included, many of which you probably are not aware of. Some of these may change depending on the implementation details of different C++ standard library implementations. This is because the standard states what header you need for a specific name, but does not dictate otherwise how the names in the headers are grouped. So including <iostream> for example from one implementation may include different additional names to some other implementation laid out in a different way. Which means you may get a name clash between your names and the names in the standard library. You may even get a name clash in code that previously compiled OK when moving from one compiler to another or when using a different standard library implementation with your compiler.
One final point: never use a using namespace directive (or a using declaration for namespace names) in a header file. For details see Herb Sutter's book "More Exceptional C++", items 39 and 40, or his online Guru of the Week (GotW, see
http://www.gotw.ca/gotw/index.htm) article #53 "Migrating to Namespaces", at
http://www.gotw.ca/gotw/053.htm
In short code that does not use using namespace std is either pre-C++ standard, does not use the standard library, uses using declarations only for the standard library names it uses, or always qualifies such names with the std:: prefix. The latter case, always qualifying standard library names with std::, is the position taken by many C++ programmers once they get used to it and is in fact now my preference.
Hope this helps.