RVO/NRVO can not be disabled in C++17 in Clang++?

Viewed 180

I was getting different results from the same snippet of code running under different C++ version with Clang++. It seems like the compiler had automatically called the RVO/NRVO when I compiled the code with C++17, curious is that a bug or different feature?

Apple clang version 11.0.0 (clang-1100.0.33.17)

Running under C++11 with the following command:

clang++ test.cc -fno-elide-constructors -std=c++11 -o test

Result:

Move Constructor
Move Constructor
100

Running under C++17 with the following command:

clang++ test.cc -fno-elide-constructors -std=c++17 -o test

Result:

100

The code (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;
}
1 Answers

In C++17 the language definition changed. In the code in your question there is no temporary , and nothing to elide.

The prvalue expression can be viewed as having delayed instantiation instead. The expression auto a = getTempA(100); is by definition identical to A a(100);.

Related