【问题标题】:Confusion about delete operator in C++关于 C++ 中删除运算符的困惑
【发布时间】:2015-08-18 17:45:19
【问题描述】:

这看起来很简单的问题,但我的朋友和我争论说下面的程序调用了 UB。但我认为他是不正确的。 考虑以下程序:

#include <iostream>
int main()
{
    int* p=new int[3]();
    int* q=p;
    for(int i=0;i<3;i++)
        std::cout<<q[i]<<' ';
    delete[] q;
    std::cout<<'\n';
}

这个程序的行为是否明确定义?如果我写 delete[] p; 而不是 delete[] q; 会发生什么?有效吗?

【问题讨论】:

  • 这里怎么会有UB?
  • 注意:delete不是删除指针,而是指针指向的对象(内存)。
  • 也许this question 会有所帮助。
  • @PravasiMeet 我想知道你为什么认为可能存在 UB。通常,如果您认为有问题,您有理由这样做。我想知道原因。

标签: c++ arrays variable-assignment delete-operator


【解决方案1】:

是的,程序定义明确。首先,您创建一个分配给新分配内存的指针。

int* p=new int[3]();

然后创建另一个指向该内存的指针

int* q=p;

然后您使用该指针将数据分配到该内存中。之后,您删除指向q 的内存,这与p 相同,这没关系。程序返回,一切正常

delete 不关心你使用什么变量。重要的是,指针指向的内存是用new 创建的,并且您只在内存上调用了一次 delete。

【讨论】:

  • @PravasiMeet 是的。只要指针指向使用new 分配的内存,它就会是安全的。不要在两个变量上调用delete,因为这是未定义的行为。我还建议您使用智能指针,然后您不必担心这些事情。
  • 正如进一步的评论:如果它按照您朋友建议的方式工作,您必须从“原始”变量中删除,那么许多标准库容器将是不可能的,例如很多代码使用 std::unique_ptr 将是 UB。例如,任何看起来像这样的代码:X * x = new X(); if(x-&gt;is_good()) { ptr.reset(x); } else { dispose_of(x); }
【解决方案2】:

new[] 运算符返回的指针不是分配内存的开始,而是指向第一个对象(或索引 0 处的对象)。现在,based on the compiler you're using,运行时系统将对象的数量 n 存储在某个位置,如果您只知道 p 指向的内存位置,就可以在其中检索它。

According to this blog,删除一个向量反向执行这个操作:

当你执行“delete[] p”时,你是在说,“p 指向一堆 对象,但我不会告诉你有多少。”在这种情况下,编译器 需要生成额外的代码来跟踪它需要多少 破坏。这些额外的信息被保存在一个“秘密的地方”,当 向量分配有“new[]”。

由于做int *q = p本质上是指向同一个数组的第0个对象,所以相当于调用delete[] qdelete[] p

【讨论】:

    【解决方案3】:

    没有 UB。它会正常工作。这里没有太多要补充的。

    【讨论】:

      【解决方案4】:

      运算符delete 只能应用于使用运算符new 分配的内存(即地址)。如果你分配一次,你也应该释放(detele)一次,不考虑使用哪个指针(可变存储地址),所以你的代码是有效的。

      但是,请记住,在您使用 delete[] q 之后,qp 都不必使用。最好的方法是将NULL 分配给两个指针。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-16
        • 1970-01-01
        • 1970-01-01
        • 2016-12-12
        • 2013-08-17
        • 2016-04-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多