Object 实际上在 C++ 中何时被销毁? delete(ptr) 有什么作用?
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
?
使用 a[x]=Book(title,p,s)
程序执行两个步骤:
- 使用构造函数创建 Book 的实例。让我们称这个实例为“alpha”
- 使用复制构造函数创建 Book (a[x]) 的新实例。让我们称这个实例为“测试版”
到达for括号的末尾时,“alpha”生命线结束,调用析构函数。
还记得拷贝构造函数吗?使用它复制指针。没有创建成员变量的新实例。令人反感的删除部分,那些成员变量在“alpha”的生命线结束时被删除,并调用相应的析构函数。尝试访问仍由“beta”指针引用的已删除变量会导致崩溃。
有多种解决方案可以解决评论中突出显示的问题:
- 不要使用指针
- 实现拷贝构造函数
Book
没有关注 Rule of 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;
}
更简单的解决方案是争取零规则 - 编写不需要自定义 copy/move 构造函数、copy/move 运算符或析构函数的代码。让编译器生成的实现为您完成所有必要的工作:
#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;
}
没有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
?
使用 a[x]=Book(title,p,s)
程序执行两个步骤:
- 使用构造函数创建 Book 的实例。让我们称这个实例为“alpha”
- 使用复制构造函数创建 Book (a[x]) 的新实例。让我们称这个实例为“测试版”
到达for括号的末尾时,“alpha”生命线结束,调用析构函数。
还记得拷贝构造函数吗?使用它复制指针。没有创建成员变量的新实例。令人反感的删除部分,那些成员变量在“alpha”的生命线结束时被删除,并调用相应的析构函数。尝试访问仍由“beta”指针引用的已删除变量会导致崩溃。
有多种解决方案可以解决评论中突出显示的问题:
- 不要使用指针
- 实现拷贝构造函数
Book
没有关注 Rule of 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;
}
更简单的解决方案是争取零规则 - 编写不需要自定义 copy/move 构造函数、copy/move 运算符或析构函数的代码。让编译器生成的实现为您完成所有必要的工作:
#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;
}