views:

340

answers:

3

I was reading 'Want Speed? Pass by Value' on the C++ Next blog and created the following program to get a feel for copy elision and move semantics in C++0x: http://pastebin.com/f39c826c6

However I am perplexed by one thing.

Here is the output I get when compiled in release mode on Visual C++ 10.0 (Beta 2):

Move assign from RVO:
Construct instance 1 (no data)
Construct instance 2 (with data)
Construct instance 3 from a move of 2
Destroy instance 2
Assign to instance 1 from 3
Destroy instance 3
Destroy instance 1
Move elided: No

Move assign from RVO simple:
Construct instance 1 (no data)
Construct instance 2 (with simple data)
Assign to instance 1 from 2
Destroy instance 2
Destroy instance 1
Move elided: Yes

Move assign from NRVO:
Construct instance 1 (no data)
Construct instance 2 (with data)
Assign to instance 1 from 2
Destroy instance 2
Destroy instance 1
Move elided: Yes

Move assign from NRVO simple:
Construct instance 1 (no data)
Construct instance 2 (with simple data)
Assign to instance 1 from 2
Destroy instance 2
Destroy instance 1
Move elided: Yes

As you can see, all of the moves are elided except for the first one.

My question is why can't the compiler perform RVO with a MoveableClass(std::vector) at line 86, but can with a MoveableClass(int) at line 97? Is this just a bug with MSVC or is there a good reason for this? And if there is a good reason, why can it still perform NRVO on a MoveableClass(std::vector) at line 91?

I'd like to understand it so I can go to sleep happy :)

Thanks

+1  A: 

Hmm.

It seems that if you change the data constructor

MoveableClass::MoveableClass(std::vector<double> data)

to accept the vector by reference, like so,

MoveableClass::MoveableClass(const std::vector<double>& data)

it works fine! Why does it not work if you pass the vector by value?

Also here's a version that should compile on earlier versions of MSVC, if anybody wants to run the test there. It contains no C++0x features: http://pastebin.com/f3bcb6ed1

dvide
A: 

Maybe it'd be a good idea to update and maintain this example from cpp-next with a version of your test that fails, so there can be one comprehensive, canonical test.

Dave Abrahams
+1  A: 

Thanks for replying Dave.

I've added my tests to that example:
pastebin.com/f7c8ca0d6

Curiously it shows that all types of elisions are not being performed except for NRVO!
Edit: Actually I suppose this is because it is the only test where the object ever has a name.

I also tried other STL types and got the same result. However when trying my own non-pod types it works as expected. I can't think what's special about the STL types that could be causing this so I don't know what else to try.

I'll submit a bug report.
Edit: Submitted here

Thanks

dvide