标准不需要编译器执行返回值优化(RVO),但是从C ++ 11开始,必须移动结果。
看来,这可能会将UB引入到/破坏代码中,这在C ++ 98中是有效的。
例如:
#include <vector>
#include <iostream>
typedef std::vector<int> Vec;
struct Manager{
Vec& vec;
Manager(Vec& vec_): vec(vec_){}
~Manager(){
//vec[0]=42; for UB
vec.at(0)=42;
}
};
Vec create(){
Vec a(1,21);
Manager m(a);
return a;
}
int main(){
std::cout<<create().at(0)<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)
当使用gcc(或与此相关的clang)进行编译时(为了简化示例,-O2 -fno-inline -fno-elide-constructors我正在使用std::vector这些build-option。如果没有这些选项以及手工类和更复杂的create功能,则可能会触发相同的行为)对于C ++ 98(-std=c++98)一切正常:
return a;触发复制构造函数,它保持a原样。m称为(必须在a被销毁之前发生,因为它m是在之后构造的a)。a在析构函数中访问是没有问题的。a函数称为。结果与预期的一样:21已打印(此处为live)。 …