[英]When Does Object Actually Gets Destroyed in C++? What does delete(ptr) Do?
没有delete
的程序完美运行。 但是,在使用delete
,我没有得到任何结果。 该计划突然终止。
#include<iostream>
using namespace std;
class Book
{
string *title;
int *price,*stock;
public:
Book()
{
title=new string();
price=new int();
stock=new int();
}
Book(string n,int p,int s)
{
title=new string(n);
price=new int(p);
stock=new int(s);
}
~Book()
{
cout<<"Object Destroyed"<<endl;
// delete (title); Using Delete i am getting Wrong Results.
// delete (price);
// delete (stock);
}
void inst();
void buy();
void display();
};
void Book::display()
{
cout<<"Title :"<<*title;
cout<<" Price is :"<<*price;
cout<<" Stock is :"<<*stock;
cout<<endl;
}
int main()
{
Book a[2];
for(int x=0;x<2;x++)
{
string title;
int p,s;
cout<<"Enter title,price,stock respectively"<<endl;
cin>>title;
cin>>p;
cin>>s;
a[x]=Book(title,p,s);
}
for(int x=0;x<2;x++)
a[x].display();
}
以下是输出:
Enter title,price,stock respectively C++ 120 2 Object Destroyed Enter title,price,stock respectively JAVA 150 5 Object Destroyed Title :C++ Price is :120 Stock is :2 Title :JAVA Price is :150 Stock is :5 Object Destroyed Object Destroyed
为什么每次输入后Object Destroyed
都会被Object Destroyed
?
Book
不遵循3/5/0 规则你有一个默认构造函数和一个转换构造函数来分配内存,还有一个析构函数来释放内存,但你没有复制构造函数或复制赋值运算符(或移动构造函数或移动赋值运算符)。 因此,编译器将提供隐式实现,将指针原样从一个对象浅拷贝到另一个对象,而不是对所指向的数据进行深拷贝。
这个说法:
Book a[2];
默认构造 2 个Book
对象,并为每个对象分配数据。
这个说法:
a[x]=Book(title,p,s);
为用户的输入构造一个临时Book
对象,然后将该临时对象复制分配给数组中的现有对象,最后销毁临时对象,释放它所指向的内存。
编译器生成的复制赋值运算符将指针浅拷贝到另一个对象(泄漏它已经指向的内存),因此当临时释放内存时,分配给对象中的指针悬空。 当display()
尝试访问无效内存时,您的代码会崩溃。
试试这个:
#include <iostream>
#include <algorithm>
using namespace std;
class Book
{
string *title;
int *price, *stock;
public:
Book() :
title(new string()),
price(new int()),
stock(new int())
{
}
Book(const Book &src) :
title(new string(*src.title)),
price(new int(*src.price)),
stock(new int(*src.stock))
{
}
// C++11 and later only...
Book(Book &&src) :
title(nullptr),
price(nullptr),
stock(nullptr)
{
swap(title, src.title);
swap(price, src.price);
swap(stock, src.stock);
}
Book(string n, int p, int s) :
title(new string(n)),
price(new int(p)),
stock(new int(s))
{
}
~Book()
{
delete title;
delete price;
delete stock;
}
Book& operator=(const Book &rhs)
{
if (&rhs != this)
{
Book tmp(rhs);
swap(title, tmp.title);
swap(price, tmp.price);
swap(stock, tmp.stock);
}
return *this;
}
// C++11 and later only...
Book& operator=(Book &&rhs)
{
swap(title, rhs.title);
swap(price, rhs.price);
swap(stock, rhs.stock);
return *this;
}
...
void display();
};
void Book::display()
{
cout << "Title :" << *title;
cout << " Price is :" << *price;
cout << " Stock is :" << *stock;
cout << endl;
}
更简单的解决方案是争取零规则——编写不需要自定义复制/移动构造函数、复制/移动运算符或析构函数的代码。 让编译器生成的实现为您完成所有必要的工作:
#include <iostream>
using namespace std;
class Book
{
string title;
int price, stock;
public:
Book() :
title(), price(0), stock(0)
{
}
Book(string n, int p, int s) :
title(n), price(p), stock(s)
{
}
...
void display();
};
void Book::display()
{
cout << "Title :" << title;
cout << " Price is :" << price;
cout << " Stock is :" << stock;
cout << endl;
}
a[x]=Book(title,p,s)
程序执行两个步骤:
当到达 for 括号的末尾时,“alpha”的生命线结束并调用析构函数。
还记得复制构造函数吗? 使用它复制指针。 不会创建成员变量的新实例。 讨厌删除部分,那些成员变量在“alpha”的生命线结束时被删除,并调用相应的析构函数。 尝试访问仍由“beta”指针引用的已删除变量会导致崩溃。
正如评论中所强调的,有多种解决方案可以解决该问题:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.