Jump to content

  • Log In with Google      Sign In   
  • Create Account

c++11 move constructor question


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
8 replies to this topic

#1 noatom   Members   -  Reputation: 782

Like
1Likes
Like

Posted 03 February 2014 - 06:25 AM

Suppose I have the following:

 

class Test {};

 

Test a;

vector<Test> v;

v.push_back(std::move(a));

 

Basically,now a has been moved to the vector(so it is a part of the vector now),but,what happens if I try to access the original a?(not the one that is in the vector now?)



Sponsor:

#2 Mussi   Crossbones+   -  Reputation: 1970

Like
1Likes
Like

Posted 03 February 2014 - 06:52 AM

That depends on the implementation of the move constructor and the data you're trying to access. The variable a has not been 'moved', it still resides in the same memory location occupying the same space. The variable that's been constructed in the vector can steal contents from a. If for example a holds a pointer to an array, this pointer could be copied and then set to null for a, accessing the pointer through a would then result in a nullpointer error.


Edited by Mussi, 03 February 2014 - 08:59 AM.


#3 richardurich   Members   -  Reputation: 1187

Like
2Likes
Like

Posted 03 February 2014 - 06:59 AM

After std::move, 'a' is left in a valid but unspecified state. (http://en.cppreference.com/w/cpp/utility/move)



#4 TheComet   Members   -  Reputation: 1603

Like
0Likes
Like

Posted 03 February 2014 - 08:09 AM

Correct me if I'm wrong, but there's little point in calling std::move on an lvalue (as is the case in your code).

 

It'd make more sense like this:

vector<Test> v;
v.push_back(std::move(Test()));

see below.


Edited by TheComet, 03 February 2014 - 08:33 AM.

YOUR_OPINION >/dev/null


#5 BitMaster   Crossbones+   -  Reputation: 4088

Like
4Likes
Like

Posted 03 February 2014 - 08:26 AM

Correct me if I'm wrong, but there's little point in calling std::move on an lvalue (as is the case in your code).
 
It'd make more sense like this:



vector<Test> v;
v.push_back(std::move(Test()));


You are wrong. In your example you don't even need the std::move because 'Test()' is an xvalue as an expiring temporary. The whole point of std::move is to allow moving of what would usually be lvalues.

Edited by BitMaster, 03 February 2014 - 08:54 AM.


#6 Brother Bob   Moderators   -  Reputation: 8197

Like
7Likes
Like

Posted 03 February 2014 - 08:41 AM

 

Correct me if I'm wrong, but there's little point in calling std::move on an lvalue (as is the case in your code).
 
It'd make more sense like this:


vector<Test> v;
v.push_back(std::move(Test()));

You are wrong. In your example you don't even need the std::move because 'Test()' is an xvalue as an expiring temporary. The whole point of std::move it to allow it on what would usually be lvalues.

 

Also, if the intention is to construct a temporary object just to pass it to push_back, you should instead use emplace_back to construct it in-place inside the vector and skip the temporary object entirely.


Edited by Brother Bob, 03 February 2014 - 08:42 AM.


#7 King Mir   Members   -  Reputation: 2000

Like
0Likes
Like

Posted 05 February 2014 - 10:24 PM

Suppose I have the following:
 
class Test {};
 
Test a;
vector<Test> v;
v.push_back(std::move(a));
 
Basically,now a has been moved to the vector(so it is a part of the vector now),but,what happens if I try to access the original a?(not the one that is in the vector now?)

std::move is just a cast, converting "a" to an rvalue. Since Test does not implement an explicit move constructor, it's just copy constructed. And since Test has no members, that's a no-op.

Standard library objects that are moved are generally specified to become objects that you cannot do anything with but destroy. Some standard classes may have more defined semantics, and in many cases the use of a moved from object can be predictably relied upon. However, any classes you write can have whatever state after a move that you code up. Those semantics are dictated by your implementation of the move constructor.

Another thing to be aware of when using moveable objects with an std::vector is that the noexcept state of the move constructor can effect when objects can be moved on reallocation. So if you write an object that can be moved and put in a vector, remember to specify if it cannot throw.

#8 BitMaster   Crossbones+   -  Reputation: 4088

Like
1Likes
Like

Posted 06 February 2014 - 01:56 AM

Since Test does not implement an explicit move constructor, it's just copy constructed. And since Test has no members, that's a no-op.


Setting aside the empty-class test case problem, according to this page the compiler should implicitly generate a move constructor. So in my understanding, if the test class contained expensive to copy members (like complex std::containers) the compiler would have generated a move constructor which could have been used.

I'm happy to be corrected though.

#9 King Mir   Members   -  Reputation: 2000

Like
0Likes
Like

Posted 06 February 2014 - 03:20 PM

Since Test does not implement an explicit move constructor, it's just copy constructed. And since Test has no members, that's a no-op.


Setting aside the empty-class test case problem, according to this page the compiler should implicitly generate a move constructor. So in my understanding, if the test class contained expensive to copy members (like complex std::containers) the compiler would have generated a move constructor which could have been used.

I'm happy to be corrected though.

No, you're right, good catch.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS