删除对象与设置指针为null

时间:2018-04-23 00:46:02

标签: c++

我无法理解如何删除对象并将指针设置为null。

例如:

Class* c = new Class();

我们可以将指针设置为null

c=null;

在这种情况下,对象仍然在内存中,并没有任何指向它。我们将如何删除它?

delete c;

在这种情况下我们删除一个对象,但指针仍然指向前一个对象的地址位置。在哪些情况下可能有用?

3 个答案:

答案 0 :(得分:2)

要解除分配new分配的对象,您应该使用delete

要防止指针变为"dangling",请将指针设置为nullptr

Class* c = new Class();
delete c;    // free up the allocated memory from new
c = nullptr; // prevent dangling pointer

如果在销毁后不再使用c,则不需要将其分配给nullptr

nullptr之后指针设置为delete的原因是因为像

这样的空保护
if (c != nullptr) {
   delete c;
   c = nullptr;
}

这是冗余,因为delete已经检查指针是否仍然指向有效的内存位置。

如果已经nullptr,那么它什么都不做。

来自expr.delete#7.3

  

否则,delete-expression不会调用deallocation   功能

     

[注意:不管是什么,都会调用释放函数   是对象的析构函数还是数组的某个元素   抛出一个例外。 - 结束注释]如果操作数的值   delete-expression是空指针值,它是未指定是否是   如上所述,将调用释放函数。

答案 1 :(得分:2)

  

[设置c = null后]对象仍在内存中,没有任何内容指向它。怎么样   我们要删除它吗?

你不能 - 在这种情况下你的程序有一种叫做memory leak的bug,因为如果没有指向对象的指针,你就无法删除你分配的对象。如果您不希望程序的内存使用量随着时间的推移而增长(并且可能在某些时候耗尽其主机的内存),保留至少一个指针是非常重要的。您动态分配的每个对象,这样您就可以在使用它时保留delete对象的功能。

  

[在另一种情况下]我们删除一个对象,但指针仍然指向地址   上一个对象的位置。在哪些情况下可能有用?

指向已删除对象的指针几乎从未有用 - 尝试取消引用指针将导致undefined behavior,技术上甚至读取悬空指针的值(不解除引用它)是禁止的好(!)。不将指针设置为NULL的唯一原因是因为将指针设置为NULL将需要额外的CPU指令(以及额外的写入内存)才能执行,并且C ++尝试不会强迫您支付您不需要的开销。 ;需要付钱。所以如果你能保证你永远不会尝试使用"悬空指针"删除对象后,将其设置为NULL的效率要比将其设置为NULL的效率要高一些。

如果上述所有内容对您来说都是程序员不友好,那么您绝对正确 - 事实如此。原始指针需要程序员非常严格的行为,如果程序员没有正确处理它们,结果就是一个错误的程序(内存泄漏,或运行时崩溃,或其他未定义但不良行为)。如果您更愿意避免这种风险(并且您应该!)然后使用原始指针(例如Class *)而不是保持动态分配的对象,您可以使用&#34保持它;智能指针"例如std::unique_ptrstd::shared_ptr。智能指针类将为您提供"它自动做正确的事情"原始指针所没有的行为,代价是为您的程序增加了微不足道的开销。

答案 2 :(得分:-1)

在将其设置为delete之前,您应该nullptr指针。但如果您不再使用它,则无需将其设置为nullptr。在这种情况下,让指针悬空(指无效的内存块)就可以了。

但我总是更喜欢RAII,它表示在构造函数中分配资源并在析构函数中释放它。它减少了指针的使用。然后,您不需要使用指针来创建对象的实例。当然,这并不总是实用,但这是一个很好的做法。

// RAII implementation

class ClassA
{
    char *buffer;
public:
    ClassA(): buffer(new buffer[1000])
    {
    }

    ~ClassA()
    {
        delete buffer;
        // now *buffer is invalid (dangling pointer) but it is easy to
        // rely that this invalid code is not called anymore.
    }
}

...

int main()
{
   ClassA instance;
   // here you do not need to use a pointer.
}