 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
MirzaD Guest
|
Posted: Tue Nov 29, 2005 8:03 pm Post subject: Unexpected destructor call |
|
|
Hello
Below you will find the problematic program. It is a string wrapper
class with a bare minimum of functionality to keep things simple.
**Code**
//StringClass.h
#include <iostream>
#include <cstring>
using namespace std;
class StringClass{
char* s;
int size;
public:
char* name;
StringClass();
StringClass(char* string);
~StringClass();
StringClass operator=(StringClass &string);
friend ostream &operator<<(ostream &output, StringClass &string);
};
StringClass::StringClass(){
s = new char[0];
size = 0;
}
StringClass::StringClass(char* string){
size = strlen(string);
s = new char[size + 1];
strcpy(s,string);
}
StringClass::~StringClass(){
cout << "Destructor: " << name << endl;
delete [] s;
}
StringClass StringClass::operator=(StringClass &string){
char* temp;
try{
temp = new char[string.size + 1];
}
catch (bad_alloc ex){
exit(1);
}
strcpy(temp,string.s);
delete [] s;
s = temp;
return *this;
}
ostream &operator<<(ostream &out, StringClass &string){
out << string.s;
return out;
}
//StringClass.cpp
#include "StringClass.h"
using namespace std;
int main(){
StringClass s("test"),t;
s.name = "s";
t.name = "t";
t = s;
cout << "s = " << s << endl << "t = " << t <
return 0;
}
**End code**
The above will display the following:
Destructor: t
s = test;
t = $*%
Destructor: t
Destructor: s
Why is the destructor called on t after the assignment takes place?
This would make sense to me if t was a pointer and the destructor was
called on the object it was pointing to (the last reference to the
object was just removed). Any help/clarification is appreciated.
Regards,
Mirza
|
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Tue Nov 29, 2005 8:11 pm Post subject: Re: Unexpected destructor call |
|
|
MirzaD wrote:
| Quote: | Below you will find the problematic program. It is a string wrapper
class with a bare minimum of functionality to keep things simple.
**Code**
//StringClass.h
#include
#include
using namespace std;
class StringClass{
char* s;
int size;
public:
char* name;
StringClass();
StringClass(char* string);
~StringClass();
StringClass operator=(StringClass &string);
friend ostream &operator<<(ostream &output, StringClass &string);
};
[..]
|
The class violates the Rule of Three.
V
|
|
| Back to top |
|
 |
Alf P. Steinbach Guest
|
Posted: Tue Nov 29, 2005 8:27 pm Post subject: Re: Unexpected destructor call |
|
|
* MirzaD:
| Quote: | Hello
Below you will find the problematic program. It is a string wrapper
class with a bare minimum of functionality to keep things simple.
**Code**
//StringClass.h
#include <iostream
|
Preferentially don't include
Use <iosfwd> if necessary (but I'd avoid even that, in general).
| Quote: | #include
using namespace std;
|
_Never_ put that in a header file.
| Quote: | class StringClass{
char* s;
int size;
public:
char* name;
|
Don't provide public access to your data members.
| Quote: | StringClass();
StringClass(char* string);
|
Should be
StringClass( char const* string );
Look up the FAQ item on The Big Three: you're taking charge of copying,
and so you need a copy constructor.
| Quote: |
StringClass operator=(StringClass &string);
|
Should be
StringClass& operator=( StringClass const& string );
| Quote: | friend ostream &operator<<(ostream &output, StringClass &string);
|
Should be
friend ostream &operator<<(
ostream &output, StringClass const& string
);
| Quote: | };
StringClass::StringClass(){
s = new char[0];
size = 0;
}
|
Since this is still in the header file, needs to be declared 'inline'.
| Quote: | StringClass::StringClass(char* string){
size = strlen(string);
s = new char[size + 1];
strcpy(s,string);
}
|
Since this is still in the header file, needs to be declared 'inline'.
| Quote: | StringClass::~StringClass(){
cout << "Destructor: " << name << endl;
delete [] s;
}
|
Since this is still in the header file, needs to be declared 'inline'.
| Quote: | StringClass StringClass::operator=(StringClass &string){
char* temp;
try{
temp = new char[string.size + 1];
}
catch (bad_alloc ex){
exit(1);
}
|
That's a bit draconian. Let the client code decide what to do with an
exception.
| Quote: | strcpy(temp,string.s);
delete [] s;
s = temp;
return *this;
}
|
Since this is still in the header file, needs to be declared 'inline'.
| Quote: | ostream &operator<<(ostream &out, StringClass &string){
out << string.s;
return out;
}
|
Since this is still in the header file, needs to be declared 'inline'.
| Quote: | //StringClass.cpp
#include "StringClass.h"
using namespace std;
int main(){
StringClass s("test"),t;
s.name = "s";
t.name = "t";
t = s;
cout << "s = " << s << endl << "t = " << t <
return 0;
}
**End code**
The above will display the following:
Destructor: t
s = test;
t = $*%
Destructor: t
Destructor: s
Why is the destructor called on t after the assignment takes place?
|
Your operator= returns a copy, and you haven't defined a copy
constructor, so invoking the auto-generated copy constructor.
--
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?
|
|
| Back to top |
|
 |
MirzaD Guest
|
Posted: Tue Nov 29, 2005 8:43 pm Post subject: Re: Unexpected destructor call |
|
|
Adding the copy constructor did solve the problem. Thank you very
much.
Mirza
|
|
| Back to top |
|
 |
Jay Nabonne Guest
|
Posted: Tue Nov 29, 2005 9:26 pm Post subject: Re: Unexpected destructor call |
|
|
On Tue, 29 Nov 2005 12:03:15 -0800, MirzaD wrote:
| Quote: |
StringClass::StringClass(){
s = new char[0];
size = 0;
}
|
Unrelated to your question, but this code plus the assignment operator
together cause a bug. The above code does not produce a zero-terminated
string.
| Quote: |
StringClass StringClass::operator=(StringClass &string){
char* temp;
try{
temp = new char[string.size + 1];
}
catch (bad_alloc ex){
exit(1);
}
strcpy(temp,string.s);
|
The above line will fail if string is a default-constructed StringClass
object, since there will not be a terminating zero.
| Quote: | delete [] s;
s = temp;
return *this;
}
|
- Jay
|
|
| Back to top |
|
 |
Puppet_Sock Guest
|
Posted: Wed Nov 30, 2005 10:05 pm Post subject: Re: Unexpected destructor call |
|
|
Alf P. Steinbach wrote:
| Quote: | * MirzaD:
[snips]
StringClass::~StringClass(){
cout << "Destructor: " << name << endl;
delete [] s;
}
Since this is still in the header file, needs to be declared 'inline'.
|
What problems does not putting 'inline' here cause?
Socks
|
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Wed Nov 30, 2005 10:15 pm Post subject: Re: Unexpected destructor call |
|
|
Puppet_Sock wrote:
| Quote: | Alf P. Steinbach wrote:
* MirzaD:
[snips]
StringClass::~StringClass(){
cout << "Destructor: " << name << endl;
delete [] s;
}
Since this is still in the header file, needs to be declared 'inline'.
What problems does not putting 'inline' here cause?
|
A violation of ODR if the header is included in more than one TU.
V
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|