[英]Why delete is needed in the definition of the copy-assignment operator?
我是C ++初学者。 我正在使用C ++ Primer(第5版)进行练习。 我从Github( 这里 )找到了对练习13.8的引用,如下所示。
#include <string>
#include <iostream>
using std::cout;
using std::endl;
class HasPtr {
public:
HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0) { }
HasPtr(const HasPtr &hp) : ps(new std::string(*hp.ps)), i(hp.i) { }
HasPtr& operator=(const HasPtr &hp) {
std::string *new_ps = new std::string(*hp.ps);
delete ps; // I don't know why it is needed here?
// But when I delete this line, it also works.
ps = new_ps;
i = hp.i;
return *this;
}
void print() {
cout << *(this->ps) << endl;
cout << this->i << endl;
}
private:
std::string *ps;
int i;
};
int main() {
HasPtr hp1("hello"), hp2("world");
hp1.print();
hp1 = hp2;
cout << "After the assignment:" << endl;
hp1.print();
}
令我困惑的是HasPtr& operator=(const HasPtr &hp)
函数。 我不知道为什么delete ps;
需要在这里。 我认为这是一个错误,但在我编译代码时它起作用了。 但是,当我删除delete ps;
行时它也有效delete ps;
。 所以,我不知道是否delete ps;
是必要的,如果保留,有什么好处。
HasPtr::ps
是一个堆分配的std::string
指针。
它在所有HasPtr
构造函数中使用new
进行分配和构造。 因此,当HasPtr::ps
被另一个堆分配的指针替换时,必须使用delete
释放现有内存以避免内存泄漏。
请注意,在现代C ++中,您几乎不应该使用new
和delete
来管理这样的对象。 使用智能指针 ,比如std::unique_ptr
或std::shared_ptr
,它们可以安全方便地为您完成内存管理。
我仍然建议熟悉new
和delete
,因为大量现有代码都使用它们。 cppreference.com
是查找有关该语言的详细信息的好地方。
正如Jan Hudec在评论中提到的那样,将std::string
存储在堆上通常非常愚蠢 - std::string
是堆分配字符数组的包装器,它已经为你管理了内存。
需要防止内存泄漏 :必须使用delete
来平衡每个new
内存 。
您在构造函数中使用new
为ps
分配内存。
为new_ps
分配内存并将其分配给ps
,需要在丢失旧指针值之前释放构造函数分配的内存。
如果你省略那一行,你的程序确实会“工作”,但是它将逐渐消耗越来越多的内存,直到最终没有更多的内存。
请注意,您有另一个内存泄漏:您需要创建一个析构函数 ,并在其中调用delete ps
。
如您所见,这变得过于复杂。 更好的是 ,抛弃所有这些指针的东西,并使用std::string s
作为成员变量 - 它负责所有的内存管理。
需要删除以避免内存泄漏。
线ps = new_ps;
编辑ps
的地址指向其他地方。
ps
之前指向的内存仍然需要被释放。 删除此行的效果不会立即显示,程序仍然“正常”,但您有内存泄漏。
例如。
ps = address 0 with value 'f'; new_ps = address 1 with value 'g'
Now let ps = new_ps;
ps = address 1 with value 'g'; new_ps = address 1 with value 'g'
So address 0 is no longer something we can access, but it's not been freed either
在C ++编程中,在类对象上调用delete会自动调用类的析构函数 。
在一般实践中,析构函数保存代码以释放资源,即文件指针,删除在类中创建的对象。这样,当您在对象上调用delete时,它分配的资源被释放,即返回给系统
如果没有释放这些资源,为这些资源分配的内存将不会被返回给系统。每次调用对象时,都会丢失一部分内存,并且在一段时间内会丢失一大块内存记忆。这被称为内存泄漏 。
因此,当您在对象上调用delete时,如果已在析构函数中执行了这些操作,则可确保释放所获取的资源。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.