0

I was testing out the Return Value Optimizations in C++ Visual Studio 2022. I was surprised that the following program needed to call the copy constructor:

#include <iostream>

class A {
public:
    A() { std::cout << "Constructor calling" << std::endl; }
    A(A& a) { std::cout << "Copy Constructor calling" << std::endl; }
    A(const A& a) { std::cout << "const Copy Constructor calling" << std::endl; }
};

A& getA() { A a; return a; }

int main() {
    A a = getA();

    return 0;
}

This outputs Constructor Calling\nCopy Constructor Calling, which means it did not get optimized with NRVO. Yet when I change the program to the following (just removed the return by reference on getA()):

#include <iostream>

class A {
public:
    A() { std::cout << "Constructor calling" << std::endl; }
    A(A& a) { std::cout << "Copy Constructor calling" << std::endl; }
    A(const A& a) { std::cout << "const Copy Constructor calling" << std::endl; }
};

A getA() { A a; return a; }

int main() {
    A a = getA();

    return 0;
}

Now we get the output as just Constructor calling and no calls to the copy constructor. Why does it not get optimized when I am returning by reference?

  • 1
    The first code leads to *undefined behavior* as the reference you return will be dangling. That really makes all discussion about behavior moot. – Some programmer dude Sep 10 '22 at 04:49
  • Why are you returning reference to a local variable? [C++ Returning reference to local variable](https://stackoverflow.com/questions/4643713/c-returning-reference-to-local-variable). It becomes a dangling reference and using it is undefined behavior. – Jason Sep 10 '22 at 04:51
  • Also note NRVO does not happen for references. – Jason Sep 10 '22 at 04:55
  • It might be easier to understand if you remember that the V in NRVO stands for **Value**. :) – Some programmer dude Sep 10 '22 at 04:58

0 Answers0