每个人
我都有一些java经验,并且是c ++的初学者.
belw是我的代码,它的输出是
0 1 2 3 4 5 6 7 8 9
destructor ---s1
8791616 8785704 2
destructor ---s1
Run Code Online (Sandbox Code Playgroud)
我预计输出是
0 1 2 3 4 5 6 7 8 9
destructor ---abc
0 1 2
destructor ---s1
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么析构函数释放第一个对象的资源.如何打印我预期的输出?
#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();
}
Run Code Online (Sandbox Code Playgroud)
如果你提高编译器的警告级别,你会得到一个提示,你的类包含指针,但你没有定义Sequence(const Sequence&)或operator=(const Sequence&)(参见什么是三规则?).
因为您没有提供复制构造函数或赋值运算符,所以编译器会为您提供这些,它们执行成员分配.
当您调用时s1 = Sequence(3,"s1");,您正在执行以下操作(这对Java开发人员来说可能是意外的):
Sequence使用"s1"作为名称创建一个新的临时三个s1,其中:
si._content为指向ints刚刚创建的三个新数组的指针,泄漏旧的10个数组.si._count为3si._name为"s1"s1)(在上面的实际输出中,你看到"s1"被销毁两次),留下_content指向free'd内存(这就是为什么你在第二次调用时看到垃圾s1.show()).如果您声明这样的赋值运算符,您将获得更接近预期输出的内容:
Sequence& operator =(const Sequence& rhs)
{
if (this != &rhs)
{
delete [] _content;
_count = rhs._count;
_content = new int[_count];
_name = rhs._name + " (copy)";
for (int i = 0; i < _count ; ++i)
{
_content[i] = rhs._content[i];
}
}
return *this;
}
Run Code Online (Sandbox Code Playgroud)
但是,你不会看到:
destructor ---abc
Run Code Online (Sandbox Code Playgroud)
...因为你s1在它_name包含时不会破坏"abc".
s1当它在结束时超出范围时被销毁},这就是你看到第二个析构函数调用的原因.与您的代码,这就要求delete[]在s1._content第二次(它是根据临时删除了,你还记得).这可能会导致程序结束时发生崩溃.
我在我的赋值运算符中添加" (copy)"了_name帮助来说明这里发生的事情.
还请看一下什么是复制和交换习语?,这是一个处理带有原始指针的类的非常简洁的方法.这也将产生你的愿望作为实例的输出s1用_name的"abc"被swapPED并销毁.我已经在这里实现了这一点,还有一些其他的小改进,以便您可以看到它正常工作.
注意:创建类实例的规范方法是:
Sequence s1; // Default constructor. Do not use parentheses [http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.2]!
Sequence s2(3, "s2") // Constructor with parameters
Run Code Online (Sandbox Code Playgroud)