Link to home
Start Free TrialLog in
Avatar of mrwad99
mrwad99Flag for United Kingdom of Great Britain and Northern Ireland

asked on

Move constructor only called if marked noexcept?

Ah hello.

I have been reading http://en.cppreference.com/w/cpp/language/noexcept_spec, which states

"For example, containers such as std::vector will move their elements if the elements' move constructor is noexcept, and copy otherwise"

So to test this, I wrote the following code, which simply adds CWidget objects to a vector.  Eventually, the memory for the vector will have to be reallocated, in which case I was hoping to see my copy constructor called, as I have declared the move constructor noexcept(false).

class CWidget
{
public:
	CWidget() {}
	CWidget(const CWidget& rhs) {}
	CWidget(CWidget&& rhs) noexcept(false) {}
};


int main()
{
	std::vector<CWidget> vec1;
	int n = 0;
	while (true)
	{
		CWidget one;
		vec1.push_back(one);
		cout << "Added " << ++n << " widgets\n";
	}
}

Open in new window

This didn't happen however.  I have my copy constructor called when adding the item to the vector, but when reallocation occurs (via vector<CWidget, std::allocator<CWidget> >::_Reallocate()) I still get my move constructor called.

Can someone explain why this is please?
Avatar of evilrix
evilrix
Flag of United Kingdom of Great Britain and Northern Ireland image

You're currently declaring that the move constructor can throw (you are setting the predicate to false, which means it can throw). The semantics of move are that they are not safe if the function can throw because if an exception is thrown half-way through the move the function cannot provide one of the standard exception guarantees (in other words, the vector will be left in an unknown state). For that reason the copy constructor will be used instead if there is no way for the move to take place with a no exception guarantee.

If you change the noexcept(false) to noexcept(true) you should see that the move constructor is used. That's certainly the case for me using GCC.
Avatar of mrwad99

ASKER

Yep, the thing is though with the code as-is (with the move constructor stating that it can throw) I don't get my copy constructor called, the move constructor is still called.  I was expecting my copy constructor to be called for the very reasons that you mention...
ASKER CERTIFIED SOLUTION
Avatar of evilrix
evilrix
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of mrwad99

ASKER

Great, thanks Rx.  I hope you are well.

If you have a spare moment could you cast your eye at https://www.experts-exchange.com/questions/28938501/Fully-specialized-class-template-function.html since you are good with templates please?
As always, you are very welcome. I'll take a look at the other question for you :)
Heh. Well, the answer do your other question is pretty simple - you can't do that :)