c++ - NRVO。关闭省略。 C++11 与 C++17

标签 c++ c++11 c++17 return-value-optimization nrvo

我正在研究复制省略和 RVO/NRVO。当我使用 -fno-elide-constructors 运行 g++ 时,我看到 c++11 和 c++17 的行为不同。

我了解 c++17 在某些情况下强制使用 RVO。我假设下面的内容算作 NRVO(除非编译器首先也消除了命名变量y?)

struct rvo 
{       
        rvo () : val {0} { std::cout << "Default Constructor" << std::endl;};
        ~rvo (){ std::cout << "Destructor" << std::endl;        };
        rvo(const rvo& in){ std::cout << "Copy Constructor" << std::endl; }
        rvo(rvo&& in){ std::cout << "Move Constructor" << std::endl; }
        
        double val;
};

rvo f1(rvo& x){ 
        rvo y {x};
        y.val++;
        return y;
}

int main()
{
        rvo A{};
        rvo B {f1(A)};
        return 0;
}

在没有附加标志的情况下编译时的输出符合预期

Default Constructor
Copy Constructor
Destructor
Destructor

使用 -fno-elide-constructors--std=c++11 编译时,输出为

Default Constructor
Copy Constructor
Move Constructor
Destructor
Move Constructor
Destructor
Destructor
Destructor

这很好,因为正在创建临时文件。

我的问题是,当我使用 -fno-elide-constructors--std=c++17 进行编译时,它消除了其中一个移动。

Default Constructor
Copy Constructor
Move Constructor
Destructor
Destructor
Destructor

看起来它正在消除临时返回变量,并将函数变量y移回main中的B。即使我已经关闭了省略。是否将其视为强制性 RVO 还是我误解了一些基本内容?

我找到了这个例子,RVO/NRVO can not be disabled in C++17 in Clang++?但那个显然是 RVO,而我认为我的示例是 NRVO,因此不是强制性的。

如果有人能证实,非常感谢。

最佳答案

这是因为来自mandatory copy elision相反,对象B直接从返回值创建f(A),因此不使用移动构造函数或拷贝ctor 以及输出。

这可以从copy elision documentation看出:

Under the following circumstances, the compilers are required to omit the copy and move construction of class objects, even if the copy/move constructor and the destructor have observable side-effects. The objects are constructed directly into the storage where they would otherwise be copied/moved to. The copy/move constructors need not be present or accessible:

  • In the initialization of an object, when the initializer expression is a prvalue of the same class type (ignoring cv-qualification) as the variable type:
T x = T(T(f())); // only one call to default constructor of T, to initialize x

关于c++ - NRVO。关闭省略。 C++11 与 C++17,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75546216/

相关文章:

c++ - VS2008 C++ : how can I make recursive include directories?

c++ - 是否可以为const操作指定一个private成员变量public?

c++ - 为什么具有显式声明的 move 构造函数的类会失败 `std::is_move_constructible_v` ?

c++ - Lambda 复制赋值运算符未定义

c++ - 如何使用 std::forward 评估参数包的扩展?

c++ - Linux 中的段错误,在 Mac OS 上工作正常

c++重载和覆盖解析时间

c++ - 来自 task_for_pid() 的 EXC_BAD_ACCESS

c++ - 对于下面解释的矛盾有什么解释吗?

c++ - g++: 错误: CreateProcess 没有那个文件或目录