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
。