简体   繁体   中英

Does a return by value call the copy constructor or the copy assignment operator?

Assuming no return value optimizaiton in compiler.
In c++, when the object return-by-vaule in function, the real step is below, am I correct? Totally, call constructor third time.

local (normal constuctor) --> temp (copy constructor) ---> outside (copy constructor or copy assignemt operator)

  1. created a local object, here it calls normal constructor;
  2. created a temp object using local object, here it calls copy constructor;
  3. assign the temp object to real object outside(a), here it calls copy constructor(case1) or copy assignment operator(case2)
class Name{...};

Name func(){
    // ...
    Name local;
    return local;
}

case1:

Name outside  = func(); // call copy constructor?

case2:

Name outside;
outside = func(); // call copy assignment operator?

If I was right in the first part, what if return value optimizaiton is enabled?

This question made me think, so in that sense it is a good question. I ran the test code below on Visual Studio C++ Express 2010 in "Debug" mode.

#include <iostream>

using namespace std;

class Foo
{
public:
    Foo(int arg) { val = arg; cout<<"Constructor (normal): "<<val<<endl; }
    Foo(const Foo& ref) { val = ref.val; cout<<"Copy constructor: "<<val<<endl; }
    const Foo& operator=(const Foo& rval)
    {
        cout<<"Assignment operator from object "<<rval.val<<" to object "<<val<<endl;
        val = rval.val; 
        return *this;
    }


    int val;
};

Foo process() {Foo t(2); return t; }

int main()
{
    Foo a(1);
    a = process();

    system("pause");
    return 0;
}

The result:

Constructor (normal): 1
    Constructor (normal): 2
    Copy constructor: 2
    Assignment operator from object 2 to object 1
    Press any key to continue . . .

So Case 2 seems to be correct. After the external 'Foo' is constructed the 'Foo' object is constructed inside the function. Then there is another object created with the copy constructor and finally the assignment operator is called to copy the result to object a.

Return value optimization will depend on the compiler and settings. For example, when I build and run in release mode there is no call to the copy constructor, indicating that the temporary object is only for debug mode. (I'm not an expert on this subject.)

Copy elision/return value optimization in C++ allows it to skip calling a copy contructor.

Case 1, you are using copy construction in the return and to build the instance "outside". Either or both of these can be elided. C++ is allowed to ellide these function calls even if they have measurable side effects - no as-if rule applies.

Case 2 you are using the assignment operator to get your value into the variable "outside", the not-as-if copy elision exception does not apply here. So, you will get an assignment operator call, unless the compiler can safely elide it due to it not having side effects. In the latter case, the compiler is free to if it chooses, but it will by definition be hard for you to tell what happened.

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