简体   繁体   中英

Construction in c++11

I'm trying to learn a little more about c++ and I'm a bit confused by what my compiler is doing. I have written the following file with comments detailing what happens:

Test getTest()
{
    return Test(100, string("testing..."));
}

int main()
{
    // These two will call the initializer constructor...
    Test t1(5, string("hello"));
    Test t2(10, string("goodbye"));

    // This will not call operator=. This will call the copy constructor!
    Test t3 = t1;

    // This will call operator=(Test&)
    t3 = t2;

    // This will call operator=(Test&&) because rhs is an rvalue
    //   We will swap the resources in this operator= so that when getTest()
    //   deletes its resources, it will actually be deleting t3's old resources.
    //   Likewise, t3 will get getTest()'s resources.
    t3 = getTest();


    // I don't know what this is doing, but I know it's not calling the destructor.
    //   I beleive that the memory of t4 is simply what was returned by getTest().
    // Likewise with t5.
    Test t4(getTest());
    Test* t5 = new Test(getTest());

    Test t6(t4);

    return 0;
}

It appears that t4 and t5 aren't entering any constructors, and in fact are just using the memory allocated by getTest(). What I assumed would happen was that t4 would enter the rValue copy constructor: Test(const Test&& rhs), but it does not even though its argument is an rValue. Test t4(getTest()) does not call any destructors, which is why I assume t4 is just acquiring the memory. t6 does call the copy constructor.

I looked in the assembly code in Visual Studio 2013 and found the following:

    Test t4(getTest());
00F59B8C  push        8  
00F59B8E  lea         ecx,[t4]  
00F59B91  call        Test::__autoclassinit2 (0F51285h)  
00F59B96  lea         eax,[t4]  
00F59B99  push        eax  
00F59B9A  call        getTest (0F51456h)  
00F59B9F  add         esp,4  
00F59BA2  mov         byte ptr [ebp-4],8  

So it looks like its calling something known as autoclassinit2, then getting the memory from getTest, and finally storing it in t4?

So I guess my question is: Is this just a compiler optimization to directly give the memory from the constructor in getTest() to t4? Instead of say, 1. constructing in getTest() 2. Calling rVal copy constructor 3. destroying getTest() memory? Or is something else going on here? Thanks!

= in a declaration means 'implicit construction please' (basically) and not 'call operator='.

C++ has a concept known as elision. Elision means 'make two or more variables the same thing'. There are rules about when the compiler can do it. Unlike other optimizations, it is legal even if there are side effects.

If you initialize a variable with an unnamed temporary of the same type, the compiler can elide the temporary. If you return a local variable from a function, it can (in certain circumstances) be elided into the unnamed return value. Ditto for unnamed return of temporaries. NRVO and RVO are the keywords you want.

In many cases, if elision fails for a technical reason or compiler limitation, move implicitly occurs. However explicit move blocks elision. So knowing the rules is important for bleeding edge optimal code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM