【问题标题】:C++ / destructor - operator deleteC++ / 析构函数 - 运算符删除
【发布时间】:2014-03-13 17:04:04
【问题描述】:

我想知道我是否必须在这样的示例中删除这个指针:

class Person
{
  public:
    Person(char *name) :_name(name) {}

    // Is this delete necessary?
    ~Person() {
        cout<<"Godbay Person"<<endl;
        delete _name;
    }

  private:
    char * _name;
}

【问题讨论】:

  • 无法判断,但很可能不会。 Person 甚至无法知道指针是指向动态分配的 char 还是 char 数组。
  • "Person 甚至不知道..." name 是 Person 类的字段,所以应该知道它指向动态分配的 char 的指针。
  • @AllanBradley 在您的代码中,name 是传递给构造函数的指针的副本,因此该类不可能知道它是否是动态分配的。 (当然,在现代 C++ 中,我无法想象动态分配 charchar 数组的情况。)
  • 你无法从指针中知道它是否必须被删除。

标签: c++ memory destructor allocation delete-operator


【解决方案1】:

无论如何,这肯定是错误的。

有两种可能:

  1. 该名称是在免费商店中专门为您的对象创建的,您的对象必须承担所有权。那么这个名字就得删了。

  2. 该名称不是在免费存储中创建的(例如,作为字符串 litaral,这很有可能),或者其他一些对象正在管理该名称,因此您的对象不应承担所有权。那么任何删除都会对您的程序造成严重破坏。

那么,为什么即使在第一种情况下我也说错了呢?因为name 听起来像一个字符串,而不是单个字符,这意味着name* 将指向一个动态分配的字符数组。在这种情况下,删除它的正确方法是delete[] name

但是:如果可能,避免使用普通 (char) 指针,对于案例 1。改用一些内存管理类(字符串类或智能指针)来获取摆脱手动管理内存所有权的麻烦。 deletedelete[] 应该很少出现在您的代码中,除非您无法访问最新的 C++ 编译器。

【讨论】:

  • 在某些情况下,普通的char 指针是有效的;例如,指向的字符串必须是字符串文字的情况。在某些情况下,您别无选择;当您连接到 C 中定义的接口时。
  • @JamesKanze 对,有例外,我相应地编辑了我的答案。但是,在这两种情况下,您提到 delete[] 都是错误的,字符串要么根本不被销毁,要么应该返回到它来自的接口。可以/应该将其包装到适当的 RAII 类本身中,例如带有自定义删除器的 shared/unique_ptr
  • 在任何编写良好的代码中,delete[] 都是错误的,因为您不应该使用new[]
【解决方案2】:

这是谁拥有分配的内存的问题,在这种情况下,它看起来像人不拥有它所以没有,所以没有必要删除。像在 Person 中那样使用原始指针总是会引起有关所有权的问题,这就是为什么建议使用 shared_ptr/unique_ptr 代替甚至更好的 std::string,因为它似乎是一个字符串。

【讨论】:

    【解决方案3】:

    一般来说,每次用new创建指针时都得调用delete。

    【讨论】:

    • 这仅适用于 C++11 之前的版本。在 C++11 中,您应该使用智能指针,因此几乎您编写的任何new 都是将对象赋予unique_ptr,并且几乎 不应写入任何删除。 (例外是自己的内存管理类)。在 C++14 中,make_unique 使最后的 news 也过时了。
    • 事实上,标签是 C++ 而不是 C++11.. (:
    • 是的,但是由于 C++11 已经成为标准两年多了,general 建议应该是最新的。
    • @ArneMertz 这完全是错误的。智能指针(早在 C++11 之前就已经存在,只是名称不同)解决了一些非常具体的问题,但它们不是灵丹妙药,不能普遍使用。
    • @ArneMertz 两年多来,C++11 成为标准并不意味着它是普遍的,甚至是广泛传播的。
    【解决方案4】:

    这取决于创建过程。

    在这种情况下没有:

    Person *p = new Person("John");
    

    在这种情况下是的:

    char *str = new char[32];
    ::strcpy(str, "John");
    Person *p = new Person(str);
    

    在这种情况下是的,但使用::free 函数而不是运算符delete

    char *str = (char *)::malloc(32);
    ::strcpy(str, "John");
    Person *p = new Person(str);
    

    考虑使用std::string 代替C 字符串指针。

    【讨论】:

      猜你喜欢
      • 2016-07-11
      • 2014-09-12
      • 2013-06-14
      • 2015-10-19
      • 1970-01-01
      • 2016-05-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多