destructor execution order in C++ - c++

I have some doubts about the result of the following snippet. Thank you in advance!
why isn't the B1 destructor called? In my opinion, "Dest B" should display ahead of "Dest A"
Any explanation would be appreciated.
class A1 {
public:
A1() { cout << "Const A" << endl; }
~A1() { cout << "Dest A" << endl; }
virtual const char* ClassName() const{ return ("A"); }
};
class B1:public A1 {
public:
B1() { cout << "Const B" << endl; }
~B1() { cout << "Dest B" << endl; }
virtual const char* ClassName() const { return ("B"); }
};
void foo1(A1 *a1)
{
cout << "foo1 has been passed an object of class " << a1->ClassName() << endl;
delete a1;
}
int main()
{
B1 *b1 = new B1;
foo1(b1);
return 0;
}

Since your class A1 has non-virtual destructor, your delete a1 produces undefined behavior. It is illegal to apply delete to a pointer of type A1 * when the pointer actually points to a B1 object, unless class A1 has virtual destructor.
What you observe is just a specific manifestation of undefined behavior.
Declare A1's destructor as virtual and you should start observing the proper behavior.

Related

Static_cast to a non base class of the dynamic type

I have this program from an exercise, and I don't understand how the static_cast is working here:
#include <iostream>
using namespace std;
class A {
public:
virtual void f() const { cout << " A::f "; }
virtual void g() { cout << " A::g "; }
virtual A* n() { cout << " A::n "; return this; }
virtual void t() { cout << " A::t "; }
};
class B: public A {
public:
virtual void f() const { cout << " B::f "; }
void g() { cout << " B::g "; A::n(); }
A* n() { cout << " B::n "; return this; }
void t() { cout << " B::t "; }
};
class C: public A {
public:
virtual void f() { cout << " C::f "; }
void g() const { cout << " C::g "; }
};
int main() {
A* q2 = new B();
A* q3 = new C();
(static_cast<C*>(q2))->g(); cout << endl;
(static_cast<C*>(q2))->t(); cout << endl;
(static_cast<B*>(q3->n()))->f(); cout << endl;
return 0;
}
The output of this is:
C::g
B::t
A::n A::f
Can someone explain how it can take the function in C if C has never been constructed for the pointer q2? How does the static_cast work in this case?
The cast does not "work". You pretend to have a pointer to an instance of C but the pointer does not point to an instance of C. Using that pointer to call a method is undefined.
Your code has undefined behavior. Compilers are not required to diagnose undefined behavior and there are no restrictions on the compilers output. The output of this code could be anything.
PS: You should use the override specifier when overriding virtual methods. In this code it looks like you wanted C::f to override A::f, but it does not, and this will become apparent when you use override.
PS2: Calling a non-static method on a pointer of wrong type can sometimes appear to work when the method is not actually using this. Thats why you see "ok" output. However, that does not make it less wrong.

Lifetime of object pointed to by shared pointer

Take the following example
struct A {
int x = 0;
};
struct B {
std::shared_ptr<A> mA;
void setA(std::shared_ptr<A> a) {
mA = a;
}
};
struct C {
B initB() {
A a;
A *aPtr = &a;
B b;
b.setA(std::make_shared<A>(aPtr));
return b;
}
};
Now in main() method
C c;
B b = c.initB();
Local variable a in initB() goes out of scope one function finishes executing. However there is a shared pointer pointing to it. Will the object the shared pointer points get deleted when a goes out of scope?
Finally will *(b.mA) give a valid instance of A?
Firstly, this doesn't compile.
B initB() {
A a;
A* aPtr = &a;
B b;
b.setA(std::make_shared<A>(/*aPtr*/a););
return b;
}
You have to pass the actual object being made shared, not a pointer to it. Now, to find out the answer to this problem, we can write notifiers for each function, and add constructors and destructors so we can see what is happening.
#include <memory>
#include <iostream>
struct A {
int x = 0;
A() {
std::cout << "A's CTOR" << std::endl;
}
~A() {
std::cout << "A's DTOR" << std::endl;
}
};
struct B {
B() {
std::cout << "B's CTOR" << std::endl;
}
~B() {
std::cout << "B's DTOR" << std::endl;
}
std::shared_ptr<A> mA;
void setA(std::shared_ptr<A> a) {
std::cout << "Entering setA()" << std::endl;
mA = a;
std::cout << "Exiting setA()" << std::endl;
}
};
struct C {
C() {
std::cout << "C's CTOR" << std::endl;
}
~C() {
std::cout << "C's DTOR" << std::endl;
}
B initB() {
std::cout << "Entering initB()" << std::endl;
A a;
A* aPtr = &a;
B b;
b.setA(std::make_shared<A>(/*aPtr*/a));
std::cout << "Exiting initB()" << std::endl;
return b;
}
};
int main() {
std::cout << "Entering Main" << std::endl;
C c;
B b = c.initB();
std::cout << "Exiting Main" << std::endl;
return 0;
}
The output:
Entering Main
C's CTOR
Entering initB()
A's CTOR
B's CTOR
Entering setA()
Exiting setA()
Exiting initB()
B's DTOR
A's DTOR
Exiting Main
B's DTOR
A's DTOR
C's DTOR
Interesting, did you catch what happened? There are 2 A's DTORs. std::make_share<A>(a) actually makes a copy of a and then makes a shared_ptr to a. Since we didn't define a copy assignment operator/constructor, the compiler automatically makes one, and that is why we only have one A's CTOR. So even though I can't imagine a place where you would do this, it will have a valid instance of A.

C++: What is the order of destructor call with methods?

I got this code:
Edit: The full code:
#include <iostream>
using namespace std;
class A {
public:
A() {}
A(const A& a) {
cout << "A copy ctor" << endl;
}
virtual ~A() {
cout << "A dtor" << endl;
}
virtual void type() const {
cout << "This is A" << endl;
}
};
class B: public A {
public:
B(){}
virtual ~B() {
cout << "B dtor" << endl;
}
void type() const override {
cout << "This is B" << endl;
}
};
A f(A a) {
a.type();
return a;
}
const A& g(const A& a) {
a.type();
return a;
}
int main() {
A* pa = new B();
cout << "applying function f:" << endl;
f(*pa).type();
cout << "applying function g:" << endl;
g(*pa).type();
delete pa;
return 0;
}
I noticed when debugging the code that after making and passing a copy of *pa to f and ending the function the destructor of the copy (*pa) that was passed to f is not called.
Only when type() ended (the same line) both the copies (I assume) were erased by the destructors
I was sure that when ending the function a destructor will be called and erase the current copy which did not happened in this case. I would like to get an explanation to the order in which the constructors and desturctors are being called in the code (I am not very knowledgeable about the order when methods are involved and I could not find much about it online).
thank you.
When you do f(*pa).type();, the Copy Constructor of A is called with an A object, so it will create an A to pass into your f function. When f returns, it is a different A being returned, since it's not by ref, however, it is NOT immediately destroyed, and instead uses copy-elision to stick around until after the .type() is called.
After that point, the destructor of both the temporary object passed into f, and the temporary object return by f are destroyed, so ~A() gets called twice.

Dynamic binding and static

I guess i am having some trouble in understanding dynamic bynding.
Suppose we are having 2 classes:
class a1{ //..
virtual void print() const;
};
class a2:a1{ //...
void print() const override;
};
Why is the following true:
a2 item_son;
a1 &item_father = item_son;
item_father->print();
the print called is the one of the son.
Actually, the OP did realize the meaning of virtual overloading vs. non-virtual overloading of functions. However, I got my sample running, hence, I'd like to publish it:
#include <iostream>
class A1 {
public:
virtual void print() const
{
std::cout << "A1::print() called." << std::endl;
}
};
class A2: public A1 {
public:
void print() const override
{
std::cout << "A2::print() called." << std::endl;
}
};
class B1 {
public:
void print() const
{
std::cout << "B1::print() called." << std::endl;
}
};
class B2: public B1 {
public:
void print() const
{
std::cout << "B2::print() called." << std::endl;
}
};
using namespace std;
int main(void)
{
A2 a2;
cout << "Calling a2.print(): ";
a2.print();
A1 &a1 = a2;
cout << "Calling a1.print(): ";
a1.print();
B2 b2;
cout << "Calling b2.print(): ";
b2.print();
B1 &b1 = b2;
cout << "Calling b1.print(): ";
b1.print();
return 0;
}
Output:
Calling a2.print(): A2::print() called.
Calling a1.print(): A2::print() called.
Calling b2.print(): B2::print() called.
Calling b1.print(): B1::print() called.
Life demo on ideone

two different behavior in using default and overridden copy constructor

When I override copy constructor why it segfaults in first delete itself.
output:
$./a.out
inside ctor
inside copy-ctor
Say i am in someFunc
inside dtor
*** glibc detected *** ./a.out: free(): invalid pointer: 0xb75f3000 ***
if I do not override copy-ctor then I could see that s1.PrintVal() is getting called and then there is seg fault in *ptr that is expected.
Why there is two different behavior with and without default and overridden copy-ctor?
#include<iostream>
using namespace std;
class Sample
{
public:
int *ptr;
Sample(int i)
{
cout << "inside ctor" << endl;
ptr = new int(i);
}
Sample(const Sample &rhs)
{
cout << "inside copy-ctor" << endl;
}
~Sample()
{
cout << "inside dtor" << endl;
delete ptr;
}
void PrintVal()
{
cout <<" inside PrintVal()."<<endl;
cout << "The value is " << *ptr<<endl;
}
};
void SomeFunc(Sample x)
{
cout << "Say i am in someFunc " << endl;
}
int main()
{
Sample s1= 10;
SomeFunc(s1);
s1.PrintVal();
return 0;
}
In your copy-ctor, you don't actually copy ptr, meaning its value will be unspecified, and you'll be deleting an unspecified pointer (instead of double-deleting a normal pointer as you do with the defauly copy-ctor).
The default copy ctor copies every member by value. This will create an alias to the pointer so each class when its dtor is called will delete the pointer and cause a fault.
In almost any class where you have a pointer that is being allocate you will need to write a custom copy constructor to allocate the pointer and then copy the value.
class Sample
{
public:
int *ptr;
Sample(int i)
{
cout << "inside ctor" << endl;
ptr = new int(i);
}
Sample(const Sample &rhs)
{
ptr = new int(*rhs.ptr);
}
Sample & operator=(const Sample& other)
{
// You should also override copy assignment if you overide copy
// you don't need to allocate in this case just copy the value
*ptr = *other.ptr;
}
~Sample()
{
cout << "inside dtor" << endl;
delete ptr;
}
void PrintVal()
{
cout <<" inside PrintVal()."<<endl;
cout << "The value is " << *ptr<<endl;
}
};
You should look up the rule of three and if your in c++ 11 the rule of five