1
#include <iostream>
using namespace std;

int gc = 0;
struct A {
    int id;
    A():id(gc++) { cout << "Constructed #" << id << "\n"; }
    A(const A& b):id(gc++) { cout << "Copying from " << b.id << " to " << id << "\n"; }
    ~A() { cout << "Destructed #" << id << "\n"; }
};
A f() {
    A a;
    cout << "Exiting f()" << "\n";
    return a;
}
int main() {
    A b = f();
    cout << "Exiting main()" << "\n";
    return 0;
}

The output produced (with no optimization (-O0), and using either of these compilers: g++ 4.6.3, g++ 4.8.1, clang++ 3.0 on Ubuntu):

Constructed #0
Exiting f()
Exiting main()
Destructed #0

My guess for copy constructor not being called (despite it having observable side effects), and object a not getting destroyed in f()) is NRVO (similar case as described in: https://stackoverflow.com/a/3906038/1857518).

My questions:

  1. Is the output of this program well specified by C++ standards ?
  2. If (1) is true, then which one of the following case it is:
    • The output will always exactly be this
    • There exist a legal & finite set of outputs, say, Out (such that |Out| > 1). And a conformant compiler can produce any one from the set Out. If this is the case, what does the set Out looks like.
Community
  • 1
  • 1
abi
  • 1,368
  • 10
  • 12

1 Answers1

2

What you see in this behavior is called copy elision.

1.Is the output of this program well specified by C++ standards?

Yes the compiler is allowed to optimize the copy side effect away for such case.

2.The output will always exactly be this

No. As mentioned the compiler is allowed to optimize the copying behavior out, but doesn't necessarily need to do it.

Thus, you can't rely on any side effects being in place or removed for returned 'copies'. See also this post: Is it possible to ensure copy elision?

Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • Followup question: Is it ever possible that a temporary will be created ? The reason I ask is because this page http://msdn.microsoft.com/en-us/library/a8kfxa78.aspx says `These temporaries are created only if your program does not copy the return value to an object.` - is this something MSVC++ decides to do, or something mandated by C++ standards ? – abi Mar 11 '14 at 20:12
  • @abi _' is this something MSVC++ decides to do, or something mandated by C++ standards ?'_ I'd say the first, the standard doesn't claim to instantiate a temporary object at all, if no lvalue is assigned AFAIR. As mentioned: You **shouldn't rely** on side effects realized with copy constructor calls for such situations. – πάντα ῥεῖ Mar 11 '14 at 20:32