【问题标题】:C++ Difference between copy initialization and const reference initialization if value comes from member variable如果值来自成员变量,则复制​​初始化和 const 引用初始化之间的 C++ 区别
【发布时间】:2018-04-04 21:15:13
【问题描述】:

考虑以下几点:

#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;
};

通常如果您使用常量reference to a r-value lifetime of the r-value is extended to match the lifetime of the reference...

1.但是如果右值是对象的成员变量呢?

要么复制值,要么引用成员变量,但只要成员变量的值不改变,这都是有效的......

2。所以在我的理解中,值无论如何都必须被复制,对吧?

3.那么const string myVal1 = myObj.getMyMember1()const string &amp;myRef1 = myObj.getMyMember1()(编译器行为、性能)有区别吗?

【问题讨论】:

  • 您的函数按值返回,这意味着它返回您放入返回表达式中的内容的副本(通常)。理论上,除了decltype(myRef1) 的结果之外,您在 #3 中提到的两个代码之间的行为或性能没有区别
  • @NonCreature0714 该线程似乎没有涵盖这个问题(根本没有提到指针)
  • @NonCreature0714 我看了一下应该回答我的问题,因为它是重复的,并且看不到与成员变量相关的 const 引用的任何内容...你能解释一下为什么你认为我的问题是重复的,以便我能够更清楚地说明差异?
  • @goulashsoup 话虽如此,我尊重 M.M 的专业知识,并为错误地举起错误的旗帜道歉。

标签: c++ c++11


【解决方案1】:

技术差异可以忽略不计。 (正如 M.M 在 cmets 中指出的那样。)

首先,这个:

const string myVal1 = myObj.getMyMember1();

初始化一个字符串const,它是myObj的成员值的副本。

但是这个:

const string &myRef1 = myObj.getMyMember1();

初始化myObj的成员返回的字符串constreference to a temporary,并且永远不能重新分配。

在这两种情况下,都会创建一个副本...And adding const 向编译器承诺不会重新分配这些值。

【讨论】:

  • 我没有投反对票,但是如果成员的值发生变化,myRef1 的值将会改变是错误的,因为getMyMember1() 不返回引用。
  • myRef1 不是对成员的引用,而是对从(成员)函数返回的临时对象。
  • @DanielJour 更正,附有临时解释的链接。
  • 是的,存在技术差异,但我不知道行为上有任何实际差异,除非您将它们与 decltype 一起使用(正如 M.M 已经对问题发表评论的那样)。
【解决方案2】:

通常,如果您使用对 r-value 的常量引用,则 r-value 的生命周期会延长以匹配引用的生命周期。

这是不正确的。正确的说法是“如果您创建一个 const rvalue 引用和未命名的临时对象,则该临时对象的生命周期会延长以匹配 rvalue 引用的生命周期”。

没有临时对象意味着没有生命周期延长。特别是,当一个方法返回一个引用时,它返回一个引用。没有创建未命名的临时对象,因此没有什么可以延长它的生命周期。只有当它按值返回非引用实际对象并且该对象未命名时,因此存在未被 RVO 省略的实际未命名临时返回值对象,才有机会延长该临时对象的生命周期。

【讨论】:

  • 这段代码虽然有一个临时文件,但该方法不返回引用...
  • OP 谈到对成员的引用,即使他们的代码没有反映这一点。因此,除了对引用和值的基本混淆之外,还不清楚他们在要求什么,或者他们的困惑在哪里。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-08
  • 2018-08-28
  • 2015-04-27
  • 2017-05-01
相关资源
最近更新 更多