Initialization Order in c++ Matters

So last week I ran into a bug in my code that exposed an aspect of the c++ language that I was familiar with intellectually, but had never run into before. The initialization order of member variables in a class is in the order of their declaration in the class. Basically this means that if your class declares a, then b, then c, they will always get initialized in that order, even you have a constructor that initializes them in a different order.

In my case I was making a class that would call a function every so often, basically duplicating a Win32 Timer object functionality. I didn’t want to pull Boost libraries in, which appears to be the best possible way to accomplish this. Instead, I wrote the following class (roughly). The idea was that it would create a thread that would call my function every 1 second. When the containing object gets destructed, it would signal the thread to end and then wait for it. This is not the best async code, but it was simple enough and functional for what I needed.

class Timer
{
	std::thread timerThread_;
	bool destructing_{ false };

public:
	int ticks_{ 0 };

	Timer() : timerThread_{ [this]() { this->timerThread(); } }
	{
	}

	~Timer()
	{
		destructing_ = true;
		timerThread_.join();
	}

	void timerThread()
	{
		while (!destructing_)
		{
			std::this_thread::sleep_for(std::chrono::seconds(1));
			tick();
		}
	}

	void tick()
	{
		++ticks_;
	}
};

So after writing this code I found that my tick() function was never being called. In a debugger I quickly found that destructing_ was set to true when I was expecting it to be false. It didn’t take me long to realize what had happened. Reordering the bool and the std::thread declarations in the class fixed the problem. This was actually a rule I didn’t know about until recently, and I was glad I had listened to a CppCon talk that mentioned it, because it would have taken me a lot longer to figure out otherwise.

The main reason that I didn’t notice it initially, even being aware of the ordering rules, was that in my non-example code, the constructor code was in a .cpp file, and the member initialized bool was declared in the .h file. So the ordering is somewhat unapparent when viewing the .cpp file.

Leave a Reply

Your email address will not be published. Required fields are marked *

Complete the following to verify your humanity: * Time limit is exhausted. Please reload CAPTCHA.

This site uses Akismet to reduce spam. Learn how your comment data is processed.