Sunday, July 13, 2008

The 'I do not know nothing in C++' Series - Post 1: Of compiler optimisation and const functions

I knew that there was something called C++ when I was in 9th standard. I tried in vain to learn it during my 11th year of education and finally had to learn it in my 2nd year of Engineering as it was part of my Computer Science curriculum. I was overjoyed to learn that I could avoid using the printf and scanf statements of C as I hated those "%xxx"s as it required an additional effort from my side of the extra 'shift' key press.

However, C++ proved to be more than
just cin and cout statements and I began to appreciate it even more I learned Oriented Programming in C++. Even though one can learn the so called A-Z of C++ through innumerable online and offline resources, one can not be still sure of its subtleties. C++ will continue to surprise you everyday and will make you wonder 'Oh wow! I did not know that. Where did this come from and how?'. I intend to bring out instances such as these through this series. Hope its fun :-)

Post 1 - Of compiler optimisation and const functions

Compiler Optimisation in Action
As it turns out, the C++ compiler is very intelligent and stingy or as in technical terms, it is optimized. It does not follow the concept of either wasteful or unnecessary spending of resources. This was proved last Friday when I was just checking the .map file of a program (A file containing the function signatures, symbols etc and used by the executables to get the relocation address etc)

The program was something simila
r to this:

I expected to find the signatures of all functions defined in these classes in the map file. But, to my surprise I found out that only the constructors of the classes Base and Derived, the main function, and the VirtualFunc function of Base and Derived classes were present in the map file. Both overloads of the NonVirtualFunc function were absent.

Then, I realized (with the help of a colleague of mine) that the compiler had generated addresses and signatures of only those functions which were used in the program, and not of those which were declared.



The constructors of the two classes are needed to create the derObject object. The virtual table is also created in the constructor. The vtable needs the address of the virtual functions of the class. Hence, the signature of the VirtualFunc function of Base (created by Base ctor) and of Derived (created/overridden by the Derived ctor) classes are present in the map file, thus demystifying this mystery.

The signature of NonVirtualFuncs appear in the map file iff the derObject invokes them, thus providing the most comprehensive proof of static/compile-time optimization.



























const Functions

The 'const' keyword is a source of confusions in C++ as its presence in various positions preceding the identifier can mean different things to the compiler. It becomes even more interesting when its used in defining and declaring functions.

A const function of a class ensures that the class methods do not modify the data members of the class. An example of such method declaration is:


This ensures that iNum is not altered by the two functions an generates compiler errors when compiled.

My problem was bigger than this. I had not inherited the function as const in the derived class and hence, I had overloaded the function and not overridden it. I was getting unexpected results for the program shown next:







I scampered for my expected output for half a day around this program, wondering what on earth was happening, before realizing that I had done an overload of the function and had not overridden it.

Finally, I cracked it and concluded that every keyword has its day in C++.

Happy programming to all,
Anirudh