Tim said:
When exiting function scope, which occurs first:
a) destruction of local objects
b) copy of value for return
b
From disassembly of a debug target,
it looks like the return value is copied
before local objects are destroyed.
Is this standard behavior?
Yes.
Can the same behavior be expected for any optimisation level?
Yes.
As a [more interesting] example,
in the function 'A A::fn(void) const' here,
is 'b' destroyed before 'a' is copied or vice-versa?:
#ifndef GUARD_A_H
#define GUARD_A_H 1
#include <iostream>
class A {
private:
// representation
int I;
public:
// functions
A fn(void) const;
// operators
friend
std:
stream& operator<<(std:
stream& os, const A& a) {
return os << a.I;
}
// constructors
A(int i = 0): I(i) {
std::cerr << "A::A(int)" << std::endl;
}
A(const A& a): I(a.I) {
std::cerr << "A::A(const A&)" << std::endl;
}
~A(void) {
std::cerr << "A::~A(void)" << std::endl;
}
};
class B {
public:
// constructors
B(void) {
std::cerr << "B::B(void)" << std::endl;
}
~B(void) {
std::cerr << "B::~B(void)" << std::endl;
}
};
#endif//GUARD_A_H
#include "A.h"
A A::fn(void) const {
A a;
B b;
a.I = I + 13;
return a;
}
#include "A.h"
int main(int argc, char* argv[]) {
const A a;
const A b = a.fn();
std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;
return 0;
}
g++ -Wall -ansi -pedantic -o main main.cc A.cc
./main
A::A(int) # a in main(int, char**)
A::A(int) # a in A::fn(void) const
B::B(void) # b in A::fn(void) const
B::~B(void) # b in A::fn(void) const
a = 0 # a in main(int, char**)
b = 13 # b in main(int, char**)
A::~A(void) # b in main(int, char**)
A::~A(void) # a in main(int, char**)
Notice that the copy constructor A::A(const A&) is *never* called!
The compiler emits code to reserve space for b
then passes a reference to b to A::fn(void) as a *hidden* argument.
In A::fn(void) const, the compiler recognizes that
b is just a reference to the return value
and initializes (and modifies) it directly.
(This is the Named Return Value Optimization (NRVO).)
A::~A(void) is *not* called in A::fn(void) const
because no local object of type A was actually created.