在Clang++中,C++17中的RVO/NRVO无法禁用?

3

我发现在不同版本的C++和Clang++下,同一个代码片段的运行结果不同。在使用C++17编译代码时,编译器似乎会自动调用RVO/NRVO,这是一个bug还是不同的功能呢?

苹果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;
}

3
在C++17之前,标准通常允许省略临时对象(RVO和NRVO是省略的类型),但并不要求这样做。在C++17中,一些省略临时对象的情况变成了强制性的 - 因此不受编译器设置的影响。 - Peter
1个回答

6
在C++17中,语言定义发生了变化。在你的问题代码中没有临时变量,并且也没有省略任何内容。 prvalue表达式可以被视为具有延迟实例化。表达式auto a = getTempA(100);的定义与A a(100);完全相同。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接