简体   繁体   中英

C++ Difference between copy initialization and const reference initialization if value comes from member variable

Consider the following:

#include <iostream>

using namespace std;

class MyClass {
    public:
        MyClass(string myMemberInitValue);
        const string getMyMember1();
    private:
        string myMember;
};

MyClass::MyClass(string myMemberInitValue) :
    myMember(myMemberInitValue)
{}

const string MyClass::getMyMember1()
{
    return myMember;
}

int main()
{
    MyClass myObj("Hello World");

    const string myVal1 = myObj.getMyMember1(); // Ok
    const string &myRef1 = myObj.getMyMember1(); // A reference to an rvalue

    ...

    return 0;
};

Normally if you use a constant reference to a r-value the lifetime of the r-value is extended to match the lifetime of the reference ...

1. But what if the r-value is a member variable of an object?

Either the value gets copied or a reference to the member variable is made but that would just be valid as long as the value of the member variable doesn't change...

2. So in my understanding the value must be copied anyway, right?

3. So is there a difference between const string myVal1 = myObj.getMyMember1() and const string &myRef1 = myObj.getMyMember1() (compiler behavior, performance)?

There is a negligible technical difference. (As MM pointed out in the comments.)

Firstly, this:

const string myVal1 = myObj.getMyMember1();

Initializes a string const which is a copy of the value of the member of myObj .

But this:

const string &myRef1 = myObj.getMyMember1();

Initializes a string const reference to a temporary returned by the member of myObj , and can never be reassigned.

In both cases, a copy is made... And adding const promises the compiler those values won't be reassigned.

Normally if you use a constant reference to a r-value the lifetime of the r-value is extended to match the lifetime of the reference.

This is incorrect. The correct statement is "If you create a const rvalue reference to and unnamed temporary object, the lifetime of that temporary object is extended to match the lifetime of the rvalue reference".

No temporary object means no lifetime extension. In particular, when a method returns a reference, it returns a reference. There's no unnamed temporary object created, so there's nothing to have its lifetime extended. Only when it returns a non-reference actual object by value AND that object is not named, so there's an actual unnamed temporary return value object that is not elided by RVO, is there an opportunity for the lifetime of that temporary to be extended.

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