繁体   English   中英

为什么在复制赋值运算符的定义中需要删除?

[英]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 ++中,您几乎不应该使用newdelete来管理这样的对象。 使用智能指针 ,比如std::unique_ptrstd::shared_ptr ,它们可以安全方便地为您完成内存管理。

我仍然建议熟悉newdelete ,因为大量现有代码都使用它们。 cppreference.com是查找有关该语言的详细信息的好地方。

正如Jan Hudec在评论中提到的那样,将std::string存储在堆上通常非常愚蠢 - std::string是堆分配字符数组的包装器,它已经为你管理了内存。

需要防止内存泄漏 :必须使用delete来平衡每个new 内存

您在构造函数中使用newps分配内存。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM