Unexpected destructor call

M

MirzaD

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::eek:perator=(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 <<endl;
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
 
V

Victor Bazarov

MirzaD said:
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);
};
[..]

The class violates the Rule of Three.

V
 
A

Alf P. Steinbach

* MirzaD:
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 <iostream> in a header file.
Use said:
#include <cstring>

using namespace std;

_Never_ put that in a header file.

class StringClass{
char* s;
int size;

public:
char* name;

Don't provide public access to your data members.

StringClass();
StringClass(char* string);

Should be

StringClass( char const* string );

~StringClass();

Look up the FAQ item on The Big Three: you're taking charge of copying,
and so you need a copy constructor.

StringClass operator=(StringClass &string);

Should be

StringClass& operator=( StringClass const& string );

friend ostream &operator<<(ostream &output, StringClass &string);

Should be

friend ostream &operator<<(
ostream &output, StringClass const& string
);

};

StringClass::StringClass(){
s = new char[0];
size = 0;
}

Since this is still in the header file, needs to be declared 'inline'.

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'.

StringClass::~StringClass(){
cout << "Destructor: " << name << endl;
delete [] s;
}

Since this is still in the header file, needs to be declared 'inline'.

StringClass StringClass::eek:perator=(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.

strcpy(temp,string.s);
delete [] s;
s = temp;
return *this;
}

Since this is still in the header file, needs to be declared 'inline'.

ostream &operator<<(ostream &out, StringClass &string){
out << string.s;
return out;
}

Since this is still in the header file, needs to be declared 'inline'.

//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 <<endl;
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.
 
J

Jay Nabonne

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.
StringClass StringClass::eek:perator=(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.
delete [] s;
s = temp;
return *this;
}

- Jay
 
P

Puppet_Sock

Alf said:
* 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
 
V

Victor Bazarov

Puppet_Sock said:
Alf said:
* 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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,262
Messages
2,571,045
Members
48,769
Latest member
Clifft

Latest Threads

Top