程序中如下
#include <iostream>
struct A
{
A() { std::cout << "0"; }
A( const A & ) { std::cout << "1"; }
A( A && ) noexcept { std::cout << "2"; }
};
A foo()
{
A res;
return res;
}
int main()
{
const A a = foo();
(void)a;
}
我期望在 foo() 中进行命名返回值优化,因此复制或移动构造函数都不会被调用。事实上,gcc 和 clang 打印“0”。
但是调试配置中的 Visual Studio 2019 打印“02”。是否允许编译器在调试版本中避免 NRVO?
由于强制复制省略在这里不适用,是的,编译器没有义务优化任何构建中的移动,无论是调试还是优化的构建。
这是允许的,但不是必需的。
自 C++17 起强制执行的是未命名返回值优化(URVO),而不是 NRVO。然而在实践中,大多数主流编译器都采用 NRVO,因为复制省略甚至比移动操作更好,因为它只是就地构造对象。现在,即使我尝试通过在代码中调用类似 foo() 的函数并在其中添加更复杂的语句来强制 MSVS 2022 处于调试模式,它也不会调用复制/移动 ctor。