Destructor calling order from function calls different from <Effective C++> 
November 14th, 2006, 11:05 PM
| | | |
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. | 
November 14th, 2006, 11:25 PM
| | | | 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? | 
November 15th, 2006, 12:25 AM
| | | | 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:
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?
| | 
November 15th, 2006, 05:25 AM
| | | | 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. |  | | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 225,662 network members.
|