Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is the destructor of the temporary called

Tags:

c++

c++11

I wanted to know when the destructor of a temporay is called for both C++03 and C++11

Suppose I have the following case

foo method()
{
   foo f;
   ......
   ......
   return foo;
}

void doSomething()
{
   foo f = method();
   ....
}

Suppose I am using the flag -fno-elide-constructors since I would like to get a theoretical understanding of when the destructor of a temporary is called. So from the above code in C++03 when the method() is finished a copy of foo is made using its copy constructor. After that at the statement foo f = method() the copy constructor of foo is called again. In this case for C++03 when is the destructor of this tempoary (which was passed by method) called ? Is it called at the end of scope of doSomething() Now I would like to apply the same case to C++11 which involve the move semantics. In case of C++11 when method returns a copy of foo is made.Then when foo f = method() is called the move constructor of foo is called. So in case of C++11 when is the destructor of the temporary object returned from method() called ?

like image 883
James Franco Avatar asked Mar 31 '15 18:03

James Franco


2 Answers

C++03

When an implementation introduces a temporary object of a class that has a non-trivial constructor (12.1), it shall ensure that a constructor is called for the temporary object. Similarly, the destructor shall be called for a temporary with a non-trivial destructor (12.4). Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. This is true even if that evaluation ends in throwing an exception.

(12.2/3; emphasis mine)

There are two contexts in which temporaries are destroyed at a different point than the end of the full- expression. The first context is when an expression appears as an initializer for a declarator defining an object. In that context, the temporary that holds the result of the expression shall persist until the object’s initialization is complete. The object is initialized from a copy of the temporary; during this copying, an implementation can call the copy constructor many times; the temporary is destroyed after it has been copied, before or when the initialization completes. If many temporaries are created by the evaluation of the initializer, the temporaries are destroyed in reverse order of the completion of their construction.

(12.2/4; emphasis mine)

So the temporary result of method() is destroyed at the end of the initialization.

C++11

When an implementation introduces a temporary object of a class that has a non-trivial constructor (12.1, 12.8), it shall ensure that a constructor is called for the temporary object. Similarly, the destructor shall be called for a temporary with a non-trivial destructor (12.4). Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. This is true even if that evaluation ends in throwing an exception. The value computations and side effects of destroying a temporary object are associated only with the full-expression, not with any specific subexpression.

(12.2/3; emphasis mine)

C++11 doesn't explicitly say that a temporary that is used as an initializer persists until initialization is complete. Instead, there's an example in 1.9/10:

[Example:

struct S {
  S(int i): I(i) { }
  int& v() { return I; }
private:
  int I;
};

S s1(1); // full-expression is call of S::S(int)
S s2 = 2; // full-expression is call of S::S(int)

void f() {
  if (S(3).v()) // full-expression includes lvalue-to-rvalue and
                // int to bool conversions, performed before
                // temporary is deleted at end of full-expression    
  { }
}

end example]

which is presumably intended to clarify that when an object with non-trivial initialization is initialized, there is a full-expression containing a call to its constructor. This removes the need to explicitly state what is stated in 12.2/4 in C++03.

like image 156
Brian Bi Avatar answered Sep 21 '22 00:09

Brian Bi


I wanted to know when the destructor of a temporay is called for both C++03 and C++11

The destructor of an R-Value (temporary) is called at the end of the expression.

Give your code:

foo method()
{
   foo f;
   ......
   ......
   return foo;
}

void doSomething()
{
   foo f = method();
   ....
}

method() creates an object. When that object goes out of scope (at the end of method), the destructor is called (in the event of no optimisations).

The call "foo f="... causes the copy constructor for foo to be called. After that the expression ends, causing the returned object (temporary) to be destructed. The object "f"'s destructor is called when it goes out of scope at the end of doSomething.

like image 21
Werner Erasmus Avatar answered Sep 22 '22 00:09

Werner Erasmus