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

标签 c++

我是 C++ 初学者。我正在做 C++ Primer(第 5 版)中的练习。我找到了一个引用 来自 Github ( Here ) 的练习 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;,保留有什么好处。

最佳答案

HasPtr::ps 是堆分配的 std::string指针。

它是使用new分配和构造的在所有 HasPtr 构造函数中。因此,当 HasPtr::ps 被另一个堆分配指针替换时,必须使用 delete 释放现有内存。以避免内存泄漏。

请注意,在现代 C++ 中,您应该几乎永远不要使用newdelete 来管理这样的对象。请改用智能指针,例如std::unique_ptrstd::shared_ptr ,它会安全方便地为您管理内存。

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

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

关于c++ - 为什么在复制赋值运算符的定义中需要删除?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34652792/

相关文章:

C++ - 双重自由或腐败 - 我找不到原因

c++ - 如何在已执行的方法中传递字段的值?

c++ - 使用 libpcap 收集有关连接的统计信息

c++ - upnp 从 openWRT 路由器发现 Philips hue

c++ - 函数模板参数推导和继承

c++ - 在使用 QPainterPath 绘制自由路径时找到交叉线

c++ - #define 与运算符一起使用

c++ - 为什么要在 Linux 中挂载文件

C++:重新使用打印到控制台的行

C++ 运算符优先级?