【发布时间】:2020-05-12 04:30:40
【问题描述】:
我在使用 Clang++ 的不同 C++ 版本下运行的相同 sn-p 代码得到了不同的结果。当我用 C++17 编译代码时,编译器似乎自动调用了 RVO/NRVO,好奇这是一个错误还是不同的功能?
Apple clang 版本 11.0.0 (clang-1100.0.33.17)
使用以下命令在 C++11 下运行:
clang++ test.cc -fno-elide-constructors -std=c++11 -o test
结果:
Move Constructor
Move Constructor
100
使用以下命令在 C++17 下运行:
clang++ test.cc -fno-elide-constructors -std=c++17 -o test
结果:
100
代码(test.cc):
struct A {
A() = default;
A(int v) : p(new int(v)) {}
~A() { delete p; }
A(const A&) = delete;
A& operator=(const A&) = delete;
A(A&& rhs) noexcept : p(rhs.p) {
std::cout << "Move Constructor" << std::endl;
rhs.p = nullptr;
}
A& operator=(A&& rhs) noexcept {
std::cout << "Move Operator" << std::endl;
p = rhs.p;
rhs.p = nullptr;
return *this;
}
int getPV() const { return *p; }
private:
int* p;
};
A getTempA(int v) { return A(v); }
int main(int argc, char** argv) {
auto a = getTempA(100);
std::cout << a.getPV() << std::endl;
return 0;
}
【问题讨论】:
-
在 C++17 之前,标准通常允许省略临时变量(RVO 和 NRVO 是省略的类型),但并不要求这样做。在 C++17 中,一些省略临时变量的情况成为强制性的——因此不会成为编译器设置的主题。