【问题标题】:Is there a way to delete a pointer that has not been assigned with new operator in the destructor? If so, should I delete it in the destructor?有没有办法在析构函数中删除一个没有用 new 运算符分配的指针?如果是这样,我应该在析构函数中删除它吗?
【发布时间】:2022-01-10 08:58:04
【问题描述】:

例如,

class Test{
private:
   int* foo;
public:
   Test(int* foo){this->foo = foo;}
}

在这种情况下,有什么方法可以在析构函数中删除 foo 吗?我是否必须在析构函数中删除 foo 或至少将其设置为 nullptr?

【问题讨论】:

  • 为什么要为成员和构造函数命名同名?
  • 您不能就不是用new 创建的东西调用delete。就那么简单。如果Test() 的调用者传入一个指向new'ed 对象的指针,则delete 它。否则不要。这就是为什么使用原始指针如此模棱两可的原因。改为使用智能指针使所有权语义更加明确。
  • 如果你的类构造函数的约定是它应该拥有指针的所有权,那么它需要负责删除指针。
  • @MatG 因为这是一种非常普遍的做法。它没有太多缺点,它可以更容易地确定这个参数的用途。
  • @MatG 如果函数体中未使用参数,则该做法相当有效(就可读性而言),这表明使用了成员初始化器列表,如Test(int* foo) : foo(foo) {}。第一次看到它可能看起来很奇怪,但很容易习惯。

标签: c++ pointers memory-leaks ownership-semantics


【解决方案1】:

当然,你可以。这是合法的语法。并且根据程序的其余部分,它可能 做你想做的事,或者它可能是双重删除(两次删除同一个指针),它会破坏堆并最终导致崩溃。 (调试编译器可能会发现这一点。)

C++ 标准模板库给我们shared_ptrunique_ptr 的原因之一是手动内存管理是困难。这并非不可能;人们这样做(或试图这样做)很多很多年了。但它也是许多运行时灾难的根源,要么是双重删除(也称为从旧的 malloc/free 例程中过早释放),要么是相反的内存泄漏。自动内存管理是 Java 的卖点之一,它是一种类似 C/C++ 的语言,没有内存错误风险。后来 C# 向用户提出了同样的建议。

我建议使用 STL 并考虑 foo 的所有权语义。也许 Test 类应该拥有它;也许它应该分享它;也许它真的应该有一个弱参考。无法从程序片段中分辨出来。我只能说你应该回顾一下现代的 C++ 内存管理思想并采用它们。

【讨论】:

  • "或者它可能是双重删除" -- 或者它可能是试图删除一个非动态变量(自动或静态存储持续时间),这也是不好。
【解决方案2】:

删除这个指针在语义上是合法的,但我想这不是你问的原因。 你问这是不是个好主意。

在 C++ 中处理原始指针通常是一种不好的做法,这个问题就是其中的一个例子。 为了让任何阅读它的人都能清楚地使用该类,如果您打算获得指针的所有权,我将使用 std::unique_ptr,如果您不打算获得引用,我将使用 std::shared_ptr

如果指针已被删除,智能指针对象将为您跟踪,它们将在其析构函数中自动删除指针。

如果您绝对必须有一个原始指针并且您需要检查它是否被删除,恐怕您唯一的选择是在删除后立即将nullptr 分配给它。

【讨论】:

    猜你喜欢
    • 2014-12-30
    • 1970-01-01
    • 2012-09-01
    • 1970-01-01
    • 2014-10-29
    • 1970-01-01
    • 2014-03-13
    • 1970-01-01
    • 2013-10-01
    相关资源
    最近更新 更多