C++ questions

Discussion of chess software programming and technical issues.

Moderator: Ras

lucasart
Posts: 3243
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

C++ questions

Post by lucasart »

I'm currently reading "The C++ programming Language" by Bjarn Stroustrup (3rd edition). And while looking at the exercises, I came across one that I would have no clue how to solve:
Given this program:

Code: Select all

#include <iostream>

int main() {
  std::cout << "Hello, world!\n";
}
modify it to produce this output:

Code: Select all

Initialize
Hello, world!
Cleanup
DO NOT change main() in any way.
Any idea ?

PS:
* this exercise is relative to chapter 10 on classes. at this point in the book, derived classes, and operators have not been formally introduced.
* please no stupid solution, like modifying the iostream file
* if you can solve it, please do not post me your solution, but rather a hint. I want to search by myself a little bit.
Last edited by lucasart on Thu Aug 30, 2012 5:59 am, edited 1 time in total.
kinderchocolate
Posts: 454
Joined: Mon Nov 01, 2010 6:55 am
Full name: Ted Wong

Re: C++ questions

Post by kinderchocolate »

lucasart wrote:I'm currently reading "The C++ programming Language" by Bjarn Stroustrup (3rd edition). And while looking at the exercises, I came across one that I would have no clue how to solve:
Given this program:

Code: Select all

#include <iostream>

int main() {
  std::cout << "Hello, world!\n";
}
modify it to produce this output:

Code: Select all

Initialize
Hello, world!
Cleanup
DO NOT change main() in any way.
Any idea ?

Such coincidence. I was also reading the book.
kinderchocolate
Posts: 454
Joined: Mon Nov 01, 2010 6:55 am
Full name: Ted Wong

Re: C++ questions

Post by kinderchocolate »

Many ways...

You don't change main(), but you can define a static variable.

Or define a macro. For example, you can define a macro for "main".

Or hack the stdio header to your user header.
lucasart
Posts: 3243
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: C++ questions

Post by lucasart »

kinderchocolate wrote:Or define a macro. For example, you can define a macro for "main".
Or hack the stdio header to your user header.
This is really ugly. I doubt that's what Bjarn had in mind...
kinderchocolate
Posts: 454
Joined: Mon Nov 01, 2010 6:55 am
Full name: Ted Wong

Re: C++ questions

Post by kinderchocolate »

The correct answer is constructor and destructor. Read 10.4. As I mentioned earlier, static variable with a constructor and destructor is the answer. I was asked this question in an interview, so I know.
mar
Posts: 2675
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: C++ questions

Post by mar »

kinderchocolate wrote:The correct answer is constructor and destructor. Read 10.4. As I mentioned earlier, static variable with a constructor and destructor is the answer. I was asked this question in an interview, so I know.
Yes that's ugly too :) But I like ugly code and it can be useful for poor man unit testing and more :)

Btw. Lucas you are learning C++ now? I thought you were strictly against it and were advocating C :)
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: C++ questions

Post by mcostalba »

In C static / global variables are initialized at zero before entering main(), and are freed after leaving main (in practice some shortcuts are taken, but the idea is this). C++ aims to keep the same semantic of C, but there is the added burden of dealing not only with C type variables, but with objects that have a constructor and a destructor that, by definition, must be called at object initialization and freeing. So the natural consequence is that in C++ some user written code (the c'tor function) is executed before entering main and some other (the d'tor function) after main returns. This seemingly innocuous extension to objects of a C semantic has very deep implications. The point is that in C and, for extension, also in C++ there is no way for the programmer to influence what happens before entering main, in particular, there is no way to determine in which order the global variables will be initialized: the only guarantee is that all the globals will be initialized before entering main, but order in which this happens is undefined by standard. For C this is not a problem because everything is just set to zero. But for C++ it is.


What happens if in the c'tor of a global variable A is accessed another global variable B that has a non default c'tor ?


If B has been already initialized at the time A c'tor is called everything works as expected, if not than a crash or a not intended behaviour occurs. The real problem is that these kind of bugs are very subtle because the order in which globals are initialized depends on platform/compiler/libraries conditions so can happen that a program compiles and runs fine for me but not for you, for instance because I use MSVC and you gcc, or because I use a library version and you another or for any other reason. The standard explicitly recommends of not relying on a given order of initialization of globals.

The above scenario is much more common than what one would think. For instance a possible tentative solution to the problem posted by Lucas could be:

Code: Select all

#include <iostream> 

struct Test {
  Test(){ std::cout << "Initialize" << std::endl; }
 ~Test(){ std::cout << "Cleanup" << std::endl; }
};
Test test;

int main() { 
  std::cout << "Hello, world!\n"; 
} 
Can you spot the problem here ?

The problem is that std::cout is itself a global object! So std::cout may or may be not already initialized at the time 'test' c'tor is called. And the above code may or may not work.


P.S: Actually the above code always works becasue std::cout is guaranteed to be constructed before the first constructor of a static object is called (http://en.cppreference.com/w/cpp/io/cout) but this is a very ad-hoc rule introduced in C++11, for instance in C++03 this is not true (http://stackoverflow.com/questions/8784 ... nitialized).


P.P.S: On the net you can find some 'clever' trick to workaround this issue: do not look at them. Just don't rely on gobal's order of initialization.
rbarreira
Posts: 900
Joined: Tue Apr 27, 2010 3:48 pm

Re: C++ questions

Post by rbarreira »

lucasart wrote: This is really ugly.
C++ by itself is already ugly so that's OK ;)
Aleks Peshkov
Posts: 983
Joined: Sun Nov 19, 2006 9:16 pm
Location: Russia
Full name: Aleks Peshkov

Re: C++ questions

Post by Aleks Peshkov »

mcostalba wrote:The point is that in C and, for extension, also in C++ there is no way for the programmer to influence what happens before entering main, in particular, there is no way to determine in which order the global variables will be initialized: the only guarantee is that all the globals will be initialized before entering main, but order in which this happens is undefined by standard.
The order of initialization is undefined between several compilation units. If you define static variables only in one source file, you have guarantee.
lucasart
Posts: 3243
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: C++ questions

Post by lucasart »

Thank you Marco! A very interesting read. I have to admit that Bjarn's book is very well written, and the exercises are very useful.

I started reading the book, thinking that I "knew" C++, and I'll probably finish it realizing that I don't know anything really.

Definitely I maintain that C is a lot easier than C++, and for many applications it is probably more advisable to stick to plain C. But once you start to truly wield its power, then C++ can be very useful. The only problem is that, out of all the people writing C++ code, only a small fraction (including you and excluding me) master it enough to get a benefit out of it.

I think where C++ really shines, is for example, in GUI applications. The OO model is really so well suited to the problem. My first goal is to understand C++ a bit deeper, and play around with GTKmm.