Jump to content
  • Advertisement
Sign in to follow this  
Quat

C++ Move Assignment

This topic is 2156 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I wrote a test class to try out move semantics, and there is something I am wondering about.  I have

 

DynamicArray<int> GetDynamicArray(int count)
{
    DynamicArray<int> temp(count);

    for(int i = 0; i < count; ++i)
        temp[i] = i;

    return temp;
}

int main()
{
    // Move constructors.
    DynamicArray<int> a1 = GetDynamicArray(5);
    DynamicArray<int> a2 = GetDynamicArray(10);
    DynamicArray<int> a3 = GetDynamicArray(20);

    // Move assignment.
    a1 = GetDynamicArray(8);

    // Copy ctor
    DynamicArray<int> a4(a1);

    // Copy assignment;
    a1 = a2;

    // Force move by casting lvalue to rvalue so move overload is called.
    // Note that a2 is in a "null/empty" state after this.
    a3 = std::move(a2);
}

 

I have cout statements in the copy/move constructors and copy/move assignment operators.  The output of this is:

 

Move constructor
Move constructor
Move constructor
Move constructor
Move assignment
Copy constructor
Copy assignment
Move assignment
Press any key to continue . . .

 

What is unexpected to me is that the line

 

a1 = GetDynamicArray(8);

 

generates two lines of output:

 

Move constructor
Move assignment

 

I expected just the Move assignment to be called.  Is this correct or am I doing something wrong? 

 

 

Share this post


Link to post
Share on other sites
Advertisement
What is probably happening is that the move constructor is moving the temp local variable to the temporary returned by the function, and then move assignment is moving from that unnamed temporary to a1.

Share this post


Link to post
Share on other sites


What is probably happening is that the move constructor is moving the temp local variable to the temporary returned by the function, and then move assignment is moving from that unnamed temporary to a1.

 

I think you are right.  I disabled the move operations and then got

 

Copy constructor
Copy assignment

 

for that line.  For some reason, I didn't think the compiler had to do a copy from the local temp to the unnamed temp in main().  I thought it would just copy assign the local temp to a1 directly. 

Share this post


Link to post
Share on other sites


For some reason, I didn't think the compiler had to do a copy from the local temp to the unnamed temp in main().

Have you tried dialing the compiler optimisations up all the way?

Share this post


Link to post
Share on other sites

Actually I thought of another question.  If

 

a1 = GetDynamicArray(8);

 

 

invokes

 

Move constructor
Move assignment

 

because it move constructs an unnamed temporary in main() and then move assigns it to a1.  Then why doesn't

 

DynamicArray<int> a1 = GetDynamicArray(5);

 

invoke

 

Move constructor

Move constructor

 

?  It seems like it needs to move construct an unnamed temporary in main() and then move construct a1 again.

Share this post


Link to post
Share on other sites


Have you tried dialing the compiler optimisations up all the way?

 

Yes, actually the release output is different from the debug output.

Share this post


Link to post
Share on other sites

Which compiler are you using? Looks like you hit an unoptimized path in the compiler.

You can try __forceinline on GetDynamicArray(), maybe it will help.

Share this post


Link to post
Share on other sites

I ran it using VS 2012, here's my output.

Ctr 5
Ctr 10
Ctr 20
Ctr 8
MoveAssigment 8
CopyCtr 8
CopyAssigment 10
MoveAssigment 10

That makes me think that your output doesn't make sense - your first 4 prints are MoveCtr, which I believe are wrong. MoveCtr has to be called with a valid rvalue object, so the regular Ctr must be called before it. As you can see - VS2012 optimizes the code and just calls the regular Ctr, no need to call the MoveCtr as well.

 

I think this is the reason why you see Ctr8 followed by a MoveAssignemt8 on the aforementioned line - you have to call the regular Ctr to create a new object before you are able to move it.

 

There's an example at the bottom this MSDN page which confirms my suspicion. You can see that the regular Ctr is always called before the MoveCtr.

Edited by N.I.B.

Share this post


Link to post
Share on other sites

Then why doesn't

 

DynamicArray<int> a1 = GetDynamicArray(5);

 

invoke

 

Move constructor

Move constructor

 

?  It seems like it needs to move construct an unnamed temporary in main() and then move construct a1 again.

How your compiler implements returning an object by value probably works by passing the function the address of the place to construct the return value. In the case of the original version, a1 has already been constructed, so it can't pass &a1 to the function, so it probably passes the address of somewhere else on the stack. In the second case, it can just pass &a1 because it knows the function will do all the construction steps for it.

Share this post


Link to post
Share on other sites


That makes me think that your output doesn't make sense - your first 4 prints are MoveCtr, which I believe are wrong. MoveCtr has to be called with a valid rvalue object, so the regular Ctr must be called before it. As you can see - VS2012 optimizes the code and just calls the regular Ctr, no need to call the MoveCtr as well.

 

He said he put log statements in the copy and move constructors and assignments, not the regular contructor, so of course the regular constructor does not show up in the log. That doesn't make it wrong.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!