Connecting Tech Pros Worldwide Forums | Help | Site Map

Destructor calling order from function calls different from <Effective C++>

Zongjun Qi
Guest
 
Posts: n/a
#1: Nov 14 '06
Hey,

In the book <Effective C++>, the author provides an example to prove
why we need "pass by reference". I redoed the example, and found
something interesting. The codes are:
##############################
#include <iostream>

class Student{
public:
Student(){
std::cout << "inside CTOR. this = " << this << std::endl <<
std::endl;
}

Student(const Student& rhs){
std::cout << "inside COPY CTOR. this = " << this << ", rhs =
"<< &rhs << std::endl << std::endl;
}

~Student(){
std::cout << "inside DTOR. this = " << this << std::endl <<
std::endl;
}
};

Student ReturnStudent(Student s){
std::cout << "inside 'ReturnStudent' function" << std::endl <<
std::endl;
return s;
}

int main(){
Student Plato;
ReturnStudent(Plato);
std::cout << "outside 'ReturnStudent' function" << std::endl <<
std::endl;
}
###########################

The thing is when you run it, I got the following output:
inside CTOR. this = 0xbfff6e30



inside COPY CTOR. this = 0xbfff6e10, rhs = 0xbfff6e30



inside 'ReturnStudent' function



inside COPY CTOR. this = 0xbfff6e20, rhs = 0xbfff6e10



inside DTOR. this = 0xbfff6e20



inside DTOR. this = 0xbfff6e10



outside 'ReturnStudent' function



inside DTOR. this = 0xbfff6e30
################################
Which means DTOR of the returned value called actually 'BEFORE' DTOR of
's' called inside the ReturnStudent function, and this is differenct to
the author said, and which I originally believed.

I am using G++ 3.2.3, Linux 2.4.21-32.EL. Compile the program using
"g++ -g main.cpp", not without any optimization.


Alf P. Steinbach
Guest
 
Posts: n/a
#2: Nov 14 '06

re: Destructor calling order from function calls different from <Effective C++>


* Zongjun Qi:
Quote:
Hey,
>
In the book <Effective C++>, the author provides an example to prove
why we need "pass by reference". I redoed the example, and found
something interesting. The codes are:
##############################
#include <iostream>
>
class Student{
public:
Student(){
std::cout << "inside CTOR. this = " << this << std::endl <<
std::endl;
}
>
Student(const Student& rhs){
std::cout << "inside COPY CTOR. this = " << this << ", rhs =
"<< &rhs << std::endl << std::endl;
}
>
~Student(){
std::cout << "inside DTOR. this = " << this << std::endl <<
std::endl;
}
};
>
Student ReturnStudent(Student s){
std::cout << "inside 'ReturnStudent' function" << std::endl <<
std::endl;
return s;
}
>
int main(){
Student Plato;
ReturnStudent(Plato);
std::cout << "outside 'ReturnStudent' function" << std::endl <<
std::endl;
}
###########################
>
The thing is when you run it, I got the following output:
inside CTOR. this = 0xbfff6e30
>
>
>
inside COPY CTOR. this = 0xbfff6e10, rhs = 0xbfff6e30
>
>
>
inside 'ReturnStudent' function
>
>
>
inside COPY CTOR. this = 0xbfff6e20, rhs = 0xbfff6e10
>
>
>
inside DTOR. this = 0xbfff6e20
>
>
>
inside DTOR. this = 0xbfff6e10
>
>
>
outside 'ReturnStudent' function
>
>
>
inside DTOR. this = 0xbfff6e30
################################
Which means DTOR of the returned value called actually 'BEFORE' DTOR of
's' called inside the ReturnStudent function, and this is differenct to
the author said, and which I originally believed.
>
I am using G++ 3.2.3, Linux 2.4.21-32.EL. Compile the program using
"g++ -g main.cpp", not without any optimization.
I don't believe Scott Meyers have written that the output must be
different from you got above. It's much more likely that you have
misinterpreted what he wrote. Here are the rules:

* Destructors of automatic objects (all objects in your program are
automatic) are called in opposite order of construction.

* Destructors of static objects are also called in opposite order of
construction.

* If you have both automatic and static objects, then the two rules
above allow, as a logical consequence of the possibility of local
static objects, that constructions and destructions sequences
such as A(), B(), ~A(), ~B() can occur, i.e. not strictly nested.

In your program destructors are called in opposite order of construction.

That's correct behavior.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Zongjun Qi
Guest
 
Posts: n/a
#3: Nov 15 '06

re: Destructor calling order from function calls different from <Effective C++>


Alf,

Thanks for your explanation. That explains well the output from G++.
However, what Meyer says in the book is a little differenct as I stated
above. But THAT' S OKAY. I guess that's a minor mistake. I think you
are right in listing the right order.

Thanks,
Zongjun

On Nov 14, 3:43 pm, "Alf P. Steinbach" <a...@start.nowrote:
Quote:
* Zongjun Qi:
>
>
>
Quote:
Hey,
>
Quote:
In the book <Effective C++>, the author provides an example to prove
why we need "pass by reference". I redoed the example, and found
something interesting. The codes are:
##############################
#include <iostream>
>
Quote:
class Student{
public:
Student(){
std::cout << "inside CTOR. this = " << this << std::endl <<
std::endl;
}
>
Quote:
Student(const Student& rhs){
std::cout << "inside COPY CTOR. this = " << this << ", rhs =
"<< &rhs << std::endl << std::endl;
}
>
Quote:
~Student(){
std::cout << "inside DTOR. this = " << this << std::endl <<
std::endl;
}
};
>
Quote:
Student ReturnStudent(Student s){
std::cout << "inside 'ReturnStudent' function" << std::endl <<
std::endl;
return s;
}
>
Quote:
int main(){
Student Plato;
ReturnStudent(Plato);
std::cout << "outside 'ReturnStudent' function" << std::endl <<
std::endl;
}
###########################
>
Quote:
The thing is when you run it, I got the following output:
inside CTOR. this = 0xbfff6e30
>
Quote:
inside COPY CTOR. this = 0xbfff6e10, rhs = 0xbfff6e30
>
Quote:
inside 'ReturnStudent' function
>
Quote:
inside COPY CTOR. this = 0xbfff6e20, rhs = 0xbfff6e10
>
Quote:
inside DTOR. this = 0xbfff6e20
>
Quote:
inside DTOR. this = 0xbfff6e10
>
Quote:
outside 'ReturnStudent' function
>
Quote:
inside DTOR. this = 0xbfff6e30
################################
Which means DTOR of the returned value called actually 'BEFORE' DTOR of
's' called inside the ReturnStudent function, and this is differenct to
the author said, and which I originally believed.
>
Quote:
I am using G++ 3.2.3, Linux 2.4.21-32.EL. Compile the program using
"g++ -g main.cpp", not without any optimization.I don't believe Scott Meyers have written that the output must be
different from you got above. It's much more likely that you have
misinterpreted what he wrote. Here are the rules:
>
* Destructors of automatic objects (all objects in your program are
automatic) are called in opposite order of construction.
>
* Destructors of static objects are also called in opposite order of
construction.
>
* If you have both automatic and static objects, then the two rules
above allow, as a logical consequence of the possibility of local
static objects, that constructions and destructions sequences
such as A(), B(), ~A(), ~B() can occur, i.e. not strictly nested.
>
In your program destructors are called in opposite order of construction.
>
That's correct behavior.
>
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Salt_Peter
Guest
 
Posts: n/a
#4: Nov 15 '06

re: Destructor calling order from function calls different from <Effective C++>



Zongjun Qi wrote:
Quote:
Hey,
>
In the book <Effective C++>, the author provides an example to prove
why we need "pass by reference". I redoed the example, and found
something interesting. The codes are:
##############################
#include <iostream>
>
class Student{
public:
Student(){
std::cout << "inside CTOR. this = " << this << std::endl <<
std::endl;
}
>
Student(const Student& rhs){
std::cout << "inside COPY CTOR. this = " << this << ", rhs =
"<< &rhs << std::endl << std::endl;
}
>
~Student(){
std::cout << "inside DTOR. this = " << this << std::endl <<
std::endl;
}
};
>
Student ReturnStudent(Student s){
std::cout << "inside 'ReturnStudent' function" << std::endl <<
std::endl;
return s;
}
>
int main(){
Student Plato;
ReturnStudent(Plato);
std::cout << "outside 'ReturnStudent' function" << std::endl <<
std::endl;
}
###########################
>
The thing is when you run it, I got the following output:
inside CTOR. this = 0xbfff6e30
>
>
>
inside COPY CTOR. this = 0xbfff6e10, rhs = 0xbfff6e30
>
>
>
inside 'ReturnStudent' function
>
>
>
inside COPY CTOR. this = 0xbfff6e20, rhs = 0xbfff6e10
>
>
>
inside DTOR. this = 0xbfff6e20
>
>
>
inside DTOR. this = 0xbfff6e10
>
>
>
outside 'ReturnStudent' function
>
>
>
inside DTOR. this = 0xbfff6e30
################################
Which means DTOR of the returned value called actually 'BEFORE' DTOR of
's' called inside the ReturnStudent function, and this is differenct to
the author said, and which I originally believed.
>
I am using G++ 3.2.3, Linux 2.4.21-32.EL. Compile the program using
"g++ -g main.cpp", not without any optimization.
The above is better explained by:

int main(){
Student Plato;
Student me = ReturnStudent(Plato);
std::cout << "outside 'ReturnStudent' function" << std::endl <<
std::endl;
}

The intended sequence of destruction now occurs correctly. Without the
Student me, the compiler just zaps both the dropped returned student
and the original parameter as fast as it can.
By the way, the author is not focusing on the sequence, its the fact
that Student, when copied, invokes the ctors for each one of its
members as well.
He's refering to the "cost" of passing by value. Members need to be
destroyed too.

Closed Thread