这个 C++ 编译器优化的名称是什么(在它自己的实例上调用一个对象自己的构造函数),它是如何工作的?

Ale*_*ter 2 c++ compiler-optimization c++11

我正在尝试学习 C++ 中的资源管理,在我的研究中我遇到了一个有趣的优化。基本上,当使用复制构造函数初始化堆栈上的对象时,该对象是一个右值对象(它是右值对象吗?),而不是调用构造函数然后调用移动构造函数,编译器只是调用原始对象的构造函数。

Object c(Object(1)); // This is the same as Object c(1);
Object c(Object(Object(Object(Object(Object(1)))))); // This is also the same as Object c(1);
Run Code Online (Sandbox Code Playgroud)
Expected flow:
1. Object(1) calls the constructor and creates a nameless Object that will be removed as soon as it's created.
2. c notices this is an rvalue, and calls the move constructor.
3. Destructor for Object(1) is called.
Run Code Online (Sandbox Code Playgroud)
Actual flow:
1. c(1) is called.
Run Code Online (Sandbox Code Playgroud)

这很聪明,但是..如何?这个技巧背后的机制是什么?即使 Object 的构造函数接受指针和许多参数,这也有效。

M.M*_*M.M 5

在 C++17 之前,此行为属于复制省略Object(x)指定创建临时对象,但编译器可以自行决定在某些情况下省略创建和销毁所有临时对象。

由于 C++17这改变了,现在Object(x)意味着迟早会有一个Objectcreated with initializer x。该对象称为结果对象结果对象的身份由此表达式出现的上下文确定,在您的代码中c是该形式的所有表达式的结果对象,并且两行完全相同Object c(1);。这适用于类别prvalue 的所有表达式。

后者为编码人员提供了更多的确定性,即不会制作不必要的副本。

  • @AlexOsheter是的,假设`f()`按值返回一个`Object`,那么这是C++17之前的复制省略上下文,并且从C++17开始,函数的*结果对象*是`c` 。除了其结果对象之外,“f()”可能会也可能不会创建其他对象,具体取决于“f()”的编码方式 (3认同)
  • @AlexOsheter 是的,这取决于编译器(假设 `f()` 按值返回 `Object`)。 (2认同)