C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Unexpected destructor call

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++)
View previous topic :: View next topic  
Author Message
MirzaD
Guest





PostPosted: Tue Nov 29, 2005 8:03 pm    Post subject: Unexpected destructor call Reply with 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>
#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





PostPosted: Tue Nov 29, 2005 8:11 pm    Post subject: Re: Unexpected destructor call Reply with quote



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





PostPosted: Tue Nov 29, 2005 8:27 pm    Post subject: Re: Unexpected destructor call Reply with quote



* 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 );


Quote:

~StringClass();

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





PostPosted: Tue Nov 29, 2005 8:43 pm    Post subject: Re: Unexpected destructor call Reply with quote

Adding the copy constructor did solve the problem. Thank you very
much.

Mirza

Back to top
Jay Nabonne
Guest





PostPosted: Tue Nov 29, 2005 9:26 pm    Post subject: Re: Unexpected destructor call Reply with quote

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





PostPosted: Wed Nov 30, 2005 10:05 pm    Post subject: Re: Unexpected destructor call Reply with quote

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





PostPosted: Wed Nov 30, 2005 10:15 pm    Post subject: Re: Unexpected destructor call Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.