Why the output is like this2?

Hello,
I have such code and I am trying to understand why the output looks like this.

Here is the output: A.f:1 B.f:1 A.f:-5 A.f:3 Exc A.f:3

I think that each token comes from:

A.f:1 B.f:1 - B b(1) is created

A.f:-5 - A *a=new B(-5) is created

A.f:3 - ??? [Don't know this one]

Exc - from throw

A.f:3 - B b(1) is destroyed

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>

using namespace std;

class A
{
public:
    virtual void f(int i){printf("A.f:%d ",i);}
    A(int i){f(i);}
    ~A(){f(3);}
};


class B:public A
{
public:
    void f(int i){printf("B.f:%d ",i);}
    B(int i=0):A(i)
    {
        if(i<0)
            throw 0;
        else
            f(i);
    }
};

B b(1);

int main()
{
    try
    {
        A *a=new B(-5);
    }
    catch (int e)
    {
        printf("Exc ");
    }

    return 0;
}
A.f:3 - ??? [Don't know this one]


That's an A object being destroyed. It's the A object created on line 33; line 33 creates a B object, and every B object is an A object. It is destroyed when the exception is thrown and everything inside the try block goes out of scope and is destroyed.
Thanks.

everything inside the try block goes out of scope and is destroyed


I always thought that objects allocated using new keyword don't get destroyed when they go out of scope.
Oh, wait one. I read it so fast I didn't spot the new. Let me look at it again.
Ah, you're throwing from the constructor of B. That changes things. If you throw from a constructor... well, things are different. Here's a page on it that goes into quite some detail:

http://www.gotw.ca/gotw/066.htm

Suffice to say that in your test case, because the A part of the object got constructed fully, it then got destructed fully when the exception was thrown. If you throw from a constructor, the object (as Herb Sutter discusses at length) effectively never comes into being.

Try this code. I took out the f() function and just had the constructor/destructor announce themselves and give their own object's memory location, so you can easily see which object is being destroyed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>

using namespace std;

class A
{
public:
  A(int i)
  {
    std::cout << "A construction, address is " << this << '\n';
  }
  ~A()
  {
    std::cout << "A destruction, address is " << this << '\n';
  }

};



class B:public A
{
public:

  B(int i=0):A(i)
  {
    std::cout << "B construction, address is " << this << '\n';
  }
  ~B()
  {
    std::cout << "B destruction, address is " << this << '\n';
  }
};

B b(1);

int main()
{
  try
    {
      A *a=new B(-5);
      throw 0;
    }
  catch (int e)
    {
      printf("Exc \n");
    }

  return 0;
}




In this code, the exception is not thrown from the constructor and as you can see, the object created with new is not then destroyed, as you expected.

The game changed when you threw from the constructor.
Last edited on
Thank you very much.
Topic archived. No new replies allowed.