Why is my destructor called twice? - c++

Suppose I hace a class Student with the method:
Student Student::method(Student x)
{
//nothing important
return x;
}
The copy constructor is called twice, once when the object x is send as a parameter and second when x is returned from the function.
Why and when is the destructor for class Student called twice when I call this method?
The call is like this: a = b.method(c), where a, b and c are Student objects.

For your example, a = b.method(c);, there are three copies that may take place, save for copy elision. The first is when the c object is copied into the function parameter x. The second is when the x object is returned from the function. The third is when the return value is copied into the a object. The first two involve the copy constructor and the last involves the copy assignment operator, unless you change it to Student a = b.method(c);, in which case they all use the copy constructor.
a, b, and c will all be destroyed at the end of their scope. The object x will be destroyed at the end of the method function. The return value of the function will be destroyed at the end of the full expression that contains it - that is, once a = b.method(c); has finished.
However, not all of these copies must occur - the compiler is allowed to elide or omit the copy/move construction of a class under certain situations. The first copy into the function parameter will occur. The second copy out of the function will be treated as a move first, before attempting to copy it. This copy or move may be elided. The final copy, from temporary return value to a, will occur if you're using copy assignment, but may be elided if you use the copy constructor (as in Student a = b.method(c);).

If two Student objects are constructed, they must be destructed. The copies into the parameter and out of the return value need destructing.

The destructor for x is called when the function returns (after x has been copied in to the return value).
The destructor for the return value is called at the end of the full-expression containing the function call (unless the return value has its lifetime extended by being assigned to a reference).
Every object with automatic storage duration that is constructed will automatically be destructed (usually in reverse order of construction). You construct two objects (x and the return value) and so there are two destructor calls.

Related

Temporary object created in case of an object declared and then assigned

I have a user defined class Fixed, with a default constructor, a parameter constructor and an assignment operator.
When I declare an object and then assign it:
Fixed a;
a = Fixed( param );
I get:
call to default constructor (line 1)
call to parameter constructor (line 2)
call to assignment operator (line 2)
call to destructor (line 2)
Of course I could (and should) prefer initialization (Fixed a(param)) over assignment.
Yet I'm trying to understand what happens on line 2.
Is a temporary object created ?
Here is what i found about temporary object.
In some cases, it is necessary for the compiler to create temporary
objects. These temporary objects can be created for the following
reasons:
...
To store the return value of a function that returns a user-defined
type. These temporaries are created only if your program does not
copy the return value to an object.
Here, the program does copy the return value of the object, so how come a temporary object is created ?
Is a temporary object created ?
Yes.
The expression Fixed( param ) will create a temporary object. This temporary object will then be passed to the assignment operator of the a object.
The statement
a = Fixed( param );
is somewhat equivalent to
{
Fixed temporary_object( param );
a.operator=( temporary_object );
}
To store the return value of a function that returns a user-defined type. These temporaries are created only if your program does not copy the return value to an object.
The line you mention is irrelevant. Fixed(param) is not a function call.
The line refers to something like:
Fixed f(param) {
return Fixed(param);
}
...
Fixed a;
a = f(param);
In this case the line explains that you shouldn't get a temporary created to hold the result of f and then copy that to a. This would be in addition to what you've seen above.
Also experiment with optimization levels.

how does returning an object work with assignment operator?

Assume we have the following operation:
Object a = b.copy();
copy() is basically a method which copies an object and returns its copy.
Object copy()
{
Object copied_Object;
/..do the copy../
return copied_Object;
}
At first I thought the return would trigger an assignment operator = and place
the result at the right field of the operation, but it turned out that actually the copy constructor gets activated and then the Object created inside the function gets destroyed. This is what I know.
My question is, can you explain to me step by step what happens when Object a = b.copy(); is executed?
Object a = b.copy();
Is an instruction to create/construct/initialize an Object. No assignment is involved.
Assignments looks like this,
object = something;
Notice the absence of a declaration of object.
Now
Object a = b.copy();
constructs a, by a b.copy() of type Object, this requires Object to have the ability to be constructed by another Object. This is of course the copy constructor. Either the compiler generated, or a defaulted, or an explicit copy constructor.
When the statement is executed, the copy function will execute and transfer the created copied_Object to the caller by either
Copy construction
Copy elision, the compiler will invoke its black-magic box and construct Object a in-place. No copy construction necessary. As hinted by Jarod.
As LogicStuff, suggests you can do
Object copy()
{
return *this;
}
This copies the contents of the b object to the return value and requires a copy constructor.
I'll steal Daniel H's comment too and conclude that
Object a = b;
will carry the exact same semantics under normal circumstances. I.e. circumstances of least surprise.

Why is the copy constructor called when we return an object from a method by value

why copy constructor is called when we return an object from a method by value. please see my below code in that i am returning an object from a method while returning control is hitting the copy constructor and then returning. i am not understood following things:
1) why it is calling copy constructor.
2)which object is passing implicitly to copy constructor,
3)to which object copy constructor will copy the content,
4)what is the necessity of copying the object content while returning. so plz help.
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class ClassA
{
int a, b;
public:
ClassA()
{
a = 10;
b = 20;
}
ClassA(ClassA &obj)
{
cout << "copy constructor called" << endl;
}
};
ClassA function (ClassA &str)
{
return str;
}
int main ()
{
ClassA str;
function(str);
//function(str);
return 0;
}
I'll try to answer all the questions at once.
The behavior you are observing is due to the way returning an object by value works in C++. First, a temporary object is copy-constructed (or move-constructed, in C++11) from the value returned by your function. Then, if this return value is used to initialize another object, such as in:
Class c = fxn();
The object c is copy-constructed (or move-constructed, in C++11), from that temporary.
This said, an implementation is allowed to elide one (in your concrete case) or both of these calls to the copy or move constructor per paragraph 12/8.31 of the C++11 Standard even though those constructors have side effects, and construct the function's return value directly in c:
When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class
object, even if the constructor selected for the copy/move operation and/or the destructor for the object
have side effects. In such cases, the implementation treats the source and target of the omitted copy/move
operation as simply two different ways of referring to the same object, and the destruction of that object
occurs at the later of the times when the two objects would have been destroyed without the optimization.122
This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which
may be combined to eliminate multiple copies):
— in a return statement in a function with a class return type, when the expression is the name of a
non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified
type as the function return type, the copy/move operation can be omitted by constructing
the automatic object directly into the function’s return value
— [...]
— when a temporary class object that has not been bound to a reference (12.2) would be copied/moved
to a class object with the same cv-unqualified type, the copy/move operation can be omitted by
constructing the temporary object directly into the target of the omitted copy/move
— [...]
The reason why I wrote that in your specific case only one of the calls to the copy or move constructor can be elided is the sentence in bold in the first bullet of the Standard quote above:
[...] (other than a function or catch-clause parameter) [...]
If you are returning a parameter of your function, copy elision is inhibited.
Also notice, that the signature of your constructor should be:
Class(Class const& c)
// ^^^^^
There is no reason for you to accept an lvalue reference to non-const in the copy constructor, since you are not going to modify the object you are copying from.
Even worse, the above would prevent copy construction from rvalues (like temporaries), so the following code would not compile:
Class foo() { return Class(); }
Even though an implementation is allowed to elide the copy, a viable and accessible copy constructor (or move constructor, if we're talking about a move) should still be present.
The function returns an object. Hence, that object must exist. Hence, that object must be created from somewhere. Clearly this means that one of its constructors shall be used. The question is, which one?
Since you chose to return str;, this is the instruction that shall be used to create it. How else could you use that return instruction to create and return an object and yet not use the copy constructor? It is clear that you need to use str to initialize the returned value, so you're not going to use the other option (the parameterless constructor).
The copy constructor is called because you call by value not by reference. Therefore a new object must be instantiated from your current object since all members of the object should have the same value in the returned instance. Because otherwise you would be returning the object it self, which would be returning by reference. In this case modifying the reference object would change the original as well. This is generally not a behavior one wants when returning by value.
ClassA function (ClassA &str)
{
return str;
}
object str will copy-constructored in a temporary object with type ClassA for further usage. However compiler can omit it due to optimization.

When reassigning variable, the destructor is not called.. (C++)

When a variable is reassigned, the destructor is not called:
Object foo = Object(a,b);
foo = Object(c,d);
so, the destructor will only be called at the end of the scope for Object(c,d), which can obviously cause problems.
Now, in this specific case it doesn't bother me too much: it is enough to declare 2 different objects:
Object foo1 = Object(a,b);
Object foo2 = Object(c,d);
In this way the destructor of both objects will be called at the end.
However, there is a case when I necessarily need to reassign a variable, i.e. in an object constructor such as:
SuperObject(Point point1, Point point2) : delay_object_(DelayObject(0)) {
double distance = distance(point1, point2);
double delay = distance / speed;
delay_object_ = DelayObject(delay);
}
In fact the DelayObject parameter is not easy to calculate (in this example I also omitted a few other passages), and I want to avoid doing it in the initialisation list.
I thought I can force the deletion by putting the object in the heap and explicitly calling the destructor:
SuperObject(Point point1, Point point2) : p_delay_object_(new DelayObject(0)) {
double distance = distance(point1, point2);
double delay = distance / speed;
delete p_delay_object_;
p_delay_object_ = new DelayObject(delay);
}
but this really looks ugly to me, as I prefer to use dynamic allocation only when strictly necessary. Am I missing something?
Cheers!
"the destructor will only be called at the end of the scope for Object(c,d)"
False. Object(c,d) is a temporary, and its destructor is called at the end of the full-expression which creates it. In this case, that's the semi-colon at the end of foo = Object(c,d);. The destructor of foo is called at end-of-scope.
The assignment operator of Object should free or re-use resources already held by foo, and copy resources held by the temporary. Not necessarily in that order (see copy-and-swap).
Edit: in response to comment.
Object foo = Object(a,b);
Either
A temporary is constructed using whatever two-argument constructor matches (a,b).
foo is constructed using the copy-constructor, passing the temporary as argument.
The temporary is destroyed.
Or
foo is constructed using whatever two-argument constructor matches (a,b).
The implementation is free to do either - this is permitted by "copy constructor elision".
foo = Object(c,d);
A temporary is constructed using whatever two-argument constructor matches (c,d).
The assignment operator for class Object is called on foo, passing the temporary as argument.
The temporary is destroyed.
Some time later, at the end of the scope, foo is destroyed.
In C++0x, move assignment would come into play if it exists for the class.
You should overload the assignment operator, which would, conceptually, copy construct the existing object and destroy the old 'this'.
class Object {
...
Object& operator= (const Object& other) {
if (this != &other) {
// copy 'other' into 'this'.
}
return *this;
}
...
};
then the foo = Object(c,d); line should do what you expect.
(Also as #Steve Jessop mentioned, the temporary object Object(c,d) will also be destructed after before the end of the scope.)
See What is The Rule of Three?.
Yes, you're forgetting that you can overload the assignment operator. The one provided by default by the compiler simply copies blindly all the fields of the objects, but you can provide your own that will do whatever you want, including disposing the resources of the object target of the assignment.
Notice that it's easy to get wrong an assignment operator (forgetting about corner cases, exception safety, ...), I advise you to read at least this part of our operator overloading FAQ, which in turn redirects to the explanation of the common copy and swap idiom, which is almost always the only sensible way to implement the assignment operator.
Edit
See in addition #Steve Jessop's answer, that considers another fundamental misunderstanding.
In all cases in which you write
SomeClass sc = SomeClass(parameters);
you are initializing a new object: you're creating a temporary (SomeClass(parameters)) and then initializing sc with a copy of it (via the copy constructor); this is both unnecessary and inefficient, the syntax to create an object on the stack in C++ is just
SomeClass sc(parameters);
Delegate calculation of DelayObject parameters to private (possibly static) methods and use them when constructing DelayObject in initializer list.

Why can't we return anything from the constructor?

C++ says that we can't return anything from the constructor? What is the historical reason behind it?
Why did Bjarne disallow contructors to return something unlike any other member function?
Because when an object is being constructed in a new statement or in a variable initializer, the object that is returned is that new object which is being constructed. What would you ever do with an object returned from a constructor? It couldn't ever be returned anywhere; it's the object being constructed that is returned. That object has already been (partially) created before the constructor is called (otherwise, the constructor wouldn't have an object to work on), and it must be what is returned from the constructor, so there is no point in making the user return it or allow them to confuse themselves by trying to return something different.
I think of a constructor as returning itself, but without having to have a return statement.
If it returns itself, then it cannot return anything else.
I can't speak for Bjarne, but the idiomatic way to look at a constructor is that it is returning the object it constructed.
Aside from the fact that having the constructor return something would give constructors two things to do instead of just one (which is generally an undesirable thing), note that constructors can't be named so it is impossible to call them explicitly.
As it's impossible to construct an expression that is an explicit call to a constructor, it would be impossible to assign or refer to a constructor's return value in any case.
Attempting to return something from a constructor just doesn't fit with the language design at all.
Constructors don't "return" objects, they initialize objects in the memory area in which they are invoked. If you declare an object of class type with static storage duration (and that type has a user-declared constructor), the memory is reserved for the lifetime of the program and the implementation ensures that the constructor is called to initialize the object at that location at the appropriate time in the program.
Similarly, if you declare and object with automatic storage duration, the implementation reserves space (informally some stack space) and invokes the constructor each time the declaration statement is executed.
In the case of a new expression, the memory is allocated dynamically and the implementation calls the appropriate constructor to initialize the object.
Note that if X is a class type, the X in all of these statements always refers to the name of the type and never the constructor which doesn't actually have a name. The syntax for declaring or defining a constructor is special, it doesn't mean that the constructor has a name. Assume that X has a user-declared constructor.
X x; // Initialize an object of type X using the default constructor
X(); // Value initialize a temporary of type X. Not an explicit constructor call.
new X(); // new expression: value-initialize a dynamically allocated X
X(a); // A function style cast
X(a, b); // Construct an X from the expression list. X must have a
// suitable constructor but the X still refers to the type.
The constructor can only yield the object itself...
Constructor don't have retunrn type bacause it already returns the refrence_id to refrence variable(which is called as an object) for ex:-
Emp e1 = new Emp(refrence_id)
here Emp is the class_name
e1 is the refrence variable
new is used for dynamic allocation
Emp() is the constructor of class Emp
in this constructor returns the refrence_id to refrence variable e1