在按值返回和按常量引用传递时避免临时构造

问题描述

我有一个通过常量引用接受 Large函数

void func(const Large& param);

一个包含 Large 的类:

class HoldsLarge {
public:
  Large GetByValue() const { return l; };

private:
  Large l;
}

如果我这样做

HoldsLarge x;
func(x.GetByValue());

我是否正确理解为 x.GetByValue() 复制构造一个临时文件,该临时文件将通过引用传递给 func?标准中是否有某些内容允许编译器完全省略临时的构造?毕竟,func 只需要 constHoldsLarge::l 的引用。

我知道我可以简单地通过常量引用返回 HoldsLarge::l,但我想防止客户端意外创建悬空引用。

解决方法

在少数情况下,允许编译器更改行为(作为优化):对于 NRVO,以及自 C++14 以来对于 new 表达式。

你不属于这些情况。

那么;只要可观察到的行为相同,as-if 规则就允许任何优化。

因此编译器可以进行优化,前提是不改变行为。

如果不知道 func,就不能安全地做到这一点。

func 可能可以通过其他方式(作为全局)访问 x.l(或别名)。

例如,跟随 func 将禁止更改。

Large* largePtr; // possibly set to &x.l by any way
void func(const Large& param)
{
    print(param.x);
    //param might be alias of largePtr
    mutate(alias->x);
    print(param.x); // const ref should see the modification
                    // whereas copy don't
}