I have some java experience and am a beginner on C++.
below is my code, its output is:
0 1 2 3 4 5 6 7 8 9
destructor ---s1
8791616 8785704 2
destructor ---s1
I expected the following output:
0 1 2 3 4 5 6 7 8 9
destructor ---abc
0 1 2
destructor ---s1
I can’t understand why the destructor releases the first object’s resource.
How can I print the output I expected?
#include <iostream>
using namespace std;
class Sequence{
public:
Sequence(int count=10,string name = "abc");
void show();
~Sequence();
int* _content;
int _count;
string _name;
};
Sequence::Sequence(int count,string name){
_count = count;
_content=new int[count];
_name = name;
for(int i=0;i<count;i++){
_content[i]=i;
}
}
Sequence::~Sequence(){
cout << "destructor ---"<<_name<<endl;
delete [] _content;
}
void Sequence::show(){
for(int i=0;i<_count;i++)
cout<<_content[i]<<" ";
cout<<endl;
}
int main(){
Sequence s1 = Sequence();
s1.show();
s1 = Sequence(3,"s1");
s1.show();
}
If you increase the warning level on your compiler, you’ll get a hint that your class contains pointers but you’re not defining
Sequence(const Sequence&)oroperator=(const Sequence&)(see What is The Rule of Three?).Because you don’t provide the copy constructor or assignment operator, the compiler provides these for you, which perform member-wise assignment.
When you call
s1 = Sequence(3,"s1");, you are doing the following (this may be unexpected to a Java developer):Sequenceof three with “s1” as its names1, which:si._contentto be the a pointer to the new array of threeintsjust created, leaking the old one of 10.si._countto3si._nameto"s1"s1) is then destroyed (in your actual output above, you see “s1” being destroyed twice), leaving_contentpointing to free’d memory (which is why you see garbage on the second call tos1.show()).If you declare an assignment operator like this, you’ll get something closer to your expected output:
You won’t, however, see:
…because you don’t destroy
s1while its_namecontains"abc".s1is destroyed when it goes out of scope at the closing}, which is why you see the second destructor call. With your code, this callsdelete[]ons1._contenta second time (it was deleted under the temporary, you’ll recall). This is likely to result in a crash right at the end of your program.I added
" (copy)"to_namein my assignment operator to help to illustrate what is happening here.Please also take a look at What is the copy-and-swap idiom?, which is a very neat way to deal with classes with raw pointers. This will also generate the output you desire as the instance of
s1with_nameof"abc"getsswapped out and destroyed. I’ve implemented this here, along with a few other little improvements so that you can see it working.N.B: The canonical way of creating an instance of a class is: