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

C++ 按值返回和按常量引用传递时避免临时构造,c++,compiler-optimization,copy-elision,C++,Compiler Optimization,Copy Elision,我有一个函数,它通过常量引用接受一个大的: void func(常量大和参数); 还有一个类,它包含一个大的: class HoldsLarge{ 公众: 大GetByValue()常量{return l;}; 私人: 大l; } 如果我这样做 HoldsLarge x; func(x.GetByValue()); 我的理解正确吗?将为x.GetByValue()构造一个临时副本,该副本将通过引用传递给func?标准中是否有允许编译器完全省略临时代码的构造的内容?毕竟,func只需要con

我有一个函数,它通过常量引用接受一个
大的

void func(常量大和参数);
还有一个类,它包含一个
大的

class HoldsLarge{
公众:
大GetByValue()常量{return l;};
私人:
大l;
}
如果我这样做

HoldsLarge x;
func(x.GetByValue());
我的理解正确吗?将为
x.GetByValue()
构造一个临时副本,该副本将通过引用传递给
func
?标准中是否有允许编译器完全省略临时代码的构造的内容?毕竟,
func
只需要
const
引用
HoldsLarge::l


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

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

在那些情况下,你不是

然后,;就好像规则允许任何优化一样,只要可观察到的行为是相同的

因此,编译器只有在不改变行为的情况下才能进行优化

如果不知道
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
}

如果签名不能更改,这是无法避免的。为什么不做另一个函数
getbyconstrefence
?(或者也可以使用智能指针
weak_ptr
…此外,对于线程,在函数运行时完全有可能修改原始的
x.l
。即使没有,也可能有对它的引用(作为全局变量或其他)outside和
func
可能会修改其中一个。这是一种行为改变。我觉得对悬挂引用的担心有些言过其实了。有人担心
std::vector::operator[]
会分发引用(或者,你知道,
)吗?好吧,编译器是不允许进行这种“优化”的。如果这样做,则函数可能会通过使用
const\u cast
来更改
l
的状态。是的,
const\u cast
不好,但它总是被错误使用。@Jarod42如果
x.GetByValue()
按值返回,那么(如果我正确阅读了标准),当您像
func(x.GetByValue())一样使用它时
,因为
func
接受一个
const&
,所以
x.GetByValue()
的返回值实际上被构造成一个
const
对象:“如果转换的初始值设定项是一个prvalue,则其类型
T4
被调整为类型
cv1 T4
”,并且
cv1
来自引用,它是
const
。然后修改该临时对象是UB,因为该对象是
const
,而该对象是
const
,因为它被构造为绑定到的引用类型是
const