When Is It Safe to Call This-> in Constructor and Destructor

When is it safe to call this- in constructor and destructor

Within any non-static member function, this points to the object that the function was called on. It's safe to use as long as that's a valid object.

Within the body of a constructor or destructor, there is a valid object of the class currently being constructed. However, if this is the base sub-object of some derived class, then only the base sub-object is valid at that time; so it's generally not safe to down-cast and try to access members of the derived class. For the same reason, you need to be careful calling virtual functions here, since they are dispatched according to the class being created or destroyed, not the final overrider.

Within the initialiser list of a constructor, you'll need to be careful only to access members that have been initialised; that is, members declared before the one currently being initialised.

Up-casting to a base class is always safe, since base sub-objects are always initialised first.

For the specific examples you just added to the question:

  • case 1 is fine (if fragile), since a has been initialised at that point. Initialising a with the value of b would be undefined, since b is initialised after a.
  • case 2 is fine: all members have been initialised at that point.
  • case 3 won't compile, since there's no suitable foo constructor. If there were, then it would depend on what that constructor did with it - whether or not it tried to access members before they were initialised.
  • case 4 would be well-formed if you added the missing ), but dangerous if you tried to use the pointer to access the object. this does not yet point to a valid bar object (only the foo part has been initialised) so accessing members of bar could give undefined behaviour. Simply checking whether the pointer is non-null is fine, and will always give true (whether or not you apply a pointless cast).

Good or bad: Calling destructor in constructor

This code is ugly but legal. When an exception is thrown from constructor, the corresponding destructor is never called. So calling it manually before throwing is needed to prevent the resource leak. The real bug here is not calling destructor manually in other cases before throwing exception.

Of course, a better way of doing this is having a separate RAII object that encapsulates commHandle. A unique_ptr with custom deleter can serve this role.

Any destructor beyond low-level libraries is a code smell in modern C++.

Is calling destructor from a catch block in constructor safe?

Despite the fact that destructors look like ordinary methods, and the explicit destruction syntax looks like a call of that method, it does not actually just call that method. Among other implementation-specific things, it also calls the destructors of base classes and data members. Throwing an exception from the constructor also causes all of those destructors to be called. So, ~Object() followed by throw will call them twice, likely with disastrous consequences.

Just move the cleanup code to an ordinary method, as someone suggested in a comment.

There's a similar syntactic problem with the function-call syntax for constructing a temporary, and with new/delete and operator new/operator delete. None of them just call the functions with the same names, even though it looks like they should.

Why there is difference in constructor and destructor calls?

When you pass by value, you are in fact creating another object for the function's lifetime .

Notice how you Pass by value two Data objects in Employee's Constructor? That means that two new Date objects are created up until Employee's constructor returns.

These values are called automatic , and once constructor exits they are automatically deleted,as a result their destructor's are called. This is where your two extra destructor calls come from.

Edit:
You create 2 Date objects , so in fact 2 Date constructor calls

You then create an employee object , so you call employee's constructor and also another 2 Date object's constructors(since each employee object has 2 Date members )

Since employee's constructor is called , you have the 2 constructor calls i mentioned above, so total 6 Date construction calls , now once your employee's constructor ends, the Date object's that were created by "call by value" are deleted and thus their destructors are called , so total 2 destructors so far,

Once Employee object gets deleted,its 2 date objects get as well,so that's another 2 destructor calls.

Then another 2 Date objects are deleted( declared in main ) and thus another 2 destructor calls.

Good luck learning C++!

Why are constructors and destructors called when they are? What are they actually doing? C++

When you pass by value to bar(), you are creating a new object, local to that function. That object is destroyed when bar() returns. It is initialised by the copy constructor A(A const &), which was implicitly generated since you don't declare one yourself. If you uncomment the copy constructor, then you will see it happening.

In general, you have to be careful when allowing objects with a non-trivial destructor to be copied. Such classes typically manage resources which are released in the destructor, and you must take care that copies don't try to manage the same resource. Always remember the Rule of Three when making classes like that.

If a virtual function is called from a constructor/destructor without qualification, does virtual dispatch occur?

Within a constructor or destructor, the sub-class object has either not yet been constructed, or has already been destroyed. As a result, virtual dispatch does not lead to the derived-class version being used, and instead the base-class version is called.

From the standard, [class.cdtor]/4:

Member functions, including virtual functions (10.3), can be called during construction or destruction (12.6.2). When a virtual function is called directly or indirectly from a constructor or from a destructor, including during the construction or destruction of the class’s non-static data members, and the object to which the call applies is the object (call it x) under construction or destruction, the function called is the final overrider in the constructor’s or destructor’s class and not the one overriding it in a more-derived class. If the virtual function call uses an explicit class member access (5.2.5) and the object expression refers to the complete object of x or one of that object’s base class subobjects but not x or one of its base class subobjects, the behavior is undefined.

An example of this is given:

struct V {
virtual void f();
virtual void g();
};
struct A : virtual V {
virtual void f();
};
struct B : virtual V {
virtual void g();
B(V*, A*);
};
struct D : A, B {
virtual void f();
virtual void g();
D() : B((A*)this, this) { }
};
B::B(V* v, A* a) {
f(); // calls V::f, not A::f
g(); // calls B::g, not D::g
v->g(); // v is base of B, the call is well-defined, calls B::g
a->f(); // undefined behavior, a’s type not a base of B
}

Also note that this can be unsafe if the function that is called is pure virtual, from [class.abstract]/6:

Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined.

destructor and copy-constructor calling..(why does it get called at these times)

Object v1(1);
// Construct(1)

Regular constructor call for an automatic stack variable (destroyed at the end of the function).

cout << "( a )" << endl;
// ( a )

Object v2(2);
// Construct(2)

Another constructor call.

v2 = v1;
// 2 = 1

The assignment operator is called because v2 was already created (we called the constructor for it) and now we're assigning one existing object to another.

cout << "( b )" << endl;
// ( b )

Object v4 = v1;
// Copy-construct(1)

The copy constructor is called here because Object v4 is still not created, so we create it as a copy of v1. The assignment is taken here to mean the same as if you did Object v4(v1)

Object *pv5;
pv5 = &v1;
pv5 = new Object(5);
// Construct(5)

Call the constructor for a heap object (destroyed explicitly with delete).

cout << "( c )" << endl;
// ( c )

func(v1);
// Copy-construct(1) <br />
// Copy-construct(1) <br />
// Destruct(1) <br />
// Destruct(1) <br />

The copy constructor is first called to copy v1 to the parameter var. It is called again to create a copy of var as return value to the caller. var is destroyed as it's popped off the stack when exiting the function. The return value is destroyed after at the expression func(v1).

cout << "( d )" << endl;
// ( d )

delete pv5;
// Destruct(5)

The object pointed at by pv5 is manually destroyed.

} // end of main
// Destruct(1) <br />
// Destruct(1) <br />
// Destruct(1) <br />

The automatic variables v1, v2, v4 (all having copied the id of v1 from either assignment or copy construction) are popped off the stack and the destructor is called for each.

C++ Constructor/Destructor invocation & Does calling new on dynamically created data delete the old data?

You are right about the pointer behavior: the memory will not be released when the pointer is reassigned.

The issue with your code (I changed the name of the variable to avoid confusion):

MyString x("test");
x = MyString("test2");

is that the second line does not call the constructor or destructor of x again. In C++, constructors and destructors are called just once per object. This code calls the assignment operator.

The sequence call would be:

  1. Call the constructor of x with "test".
  2. Call the constructor of the unnamed temporary with "test2".
  3. Call the assignment operator of x with the temporary object.
  4. Call the destructor of the temporary object.
  5. At the end of the current scope, call the destructor of x.

The assignment operator should be defined more or less this way:

const MyString &MyString::operator=(const MyString&o)
{
nlength = S.nlength; // we know this is correct!
delete []nstring;
nstring = new char[ nlength ];
strcpy( nstring, S.nstring );
return *this;
}

Naturally this code is not exception safe. What will happen if this new fails? The object will be broken! So do instead:

const MyString &MyString::operator=(MyString o)
{
swap(*this, o);
return *this;
}

This is called the copy-n-swap idiom, or something like that. The sequence of calls with this operator= when running the point 3 above would be:

  1. Call the copy constructor of o passing in the temporary.
  2. Swap the values of o and this.
  3. Calling the destructor of o, that will delete the first allocation ("test1").

Calling virtual functions inside constructors

Calling virtual functions from a constructor or destructor is dangerous and should be avoided whenever possible. All C++ implementations should call the version of the function defined at the level of the hierarchy in the current constructor and no further.

The C++ FAQ Lite covers this in section 23.7 in pretty good detail. I suggest reading that (and the rest of the FAQ) for a followup.

Excerpt:

[...] In a constructor, the virtual call mechanism is disabled because overriding from derived classes hasn’t yet happened. Objects are constructed from the base up, “base before derived”.

[...]

Destruction is done “derived class before base class”, so virtual functions behave as in constructors: Only the local definitions are used – and no calls are made to overriding functions to avoid touching the (now destroyed) derived class part of the object.

EDIT Corrected Most to All (thanks litb)



Related Topics



Leave a reply



Submit