【问题标题】:Why doesn't delete set the pointer to NULL?为什么 delete 不将指针设置为 NULL?
【发布时间】:2010-10-16 19:26:24
【问题描述】:

我一直想知道为什么在 delete 之后将指针自动设置为 NULL 不是标准的一部分。如果这得到照顾,那么由于指针无效而导致的许多崩溃都不会发生。但话虽如此,我可以想到标准会限制这一点的几个原因:

  1. 性能:

    附加指令可能会降低delete 的性能。

  2. 可能是因为const 指针。

    然后我猜想标准可以为这种特殊情况做点什么。

有人知道不允许这样做的确切原因吗?

【问题讨论】:

    标签: c++ memory-management delete-operator


    【解决方案1】:

    Stroustrup himself 回答。摘录:

    C++ 明确允许 删除归零的实现 一个左值操作数,我曾希望 实现会这样做, 但这个想法似乎没有 受到实施者的欢迎。

    但他提出的主要问题是 delete 的参数不必是左值。

    【讨论】:

    • 我认为这可以使用更多的解释。我什至不确定他在说什么......我想我必须在稍后再回来,那时我可以花几个小时来研究这个,直到我得到它。或者,您可以详细说明答案,以帮助我们更快地理解。
    • 如果标准删除为左值和右值重载会很好,所以当它是左值时它会将参数设置为nullptr。
    【解决方案2】:

    首先,设置为 null 需要一个内存存储变量。确实,您通常在变量中有一个指针,但有时您可能想删除刚刚计算出的地址处的对象。使用“无效”删除是不可能的。

    然后是表演。您可能以这样一种方式编写代码,即在 delete 完成后指针将立即超出范围。用 null 填充它只是浪费时间。而 C++ 是一种具有“不需要它?那你就不必为它付费”的意识形态的语言。

    如果您需要安全,可以为您提供各种智能指针服务,或者您可以自己编写 - 更好、更智能。

    【讨论】:

    • 好点wrt计算地址,即使它是你不经常看到的东西
    • 当您说有时您可能想要删除刚刚计算出的地址处的对象时,您是在谈论新的放置。 ???
    • @PravasiMeet 不,我的意思是delete (ptr + i)
    【解决方案3】:

    您可以有多个指向该内存的指针。如果您为删除指定的指针设置为空,但所有其他指针都没有设置,则会产生错误的安全感。指针只不过是一个地址,一个数字。它也可能是一个带有取消引用操作的 int。我的观点是,您还必须扫描每个指针以找到那些引用您刚刚删除的相同内存的指针,并将它们也清空。扫描该地址的所有指针并将它们清空将是计算密集型的,因为该语言不是为此而设计的。 (尽管其他一些语言构建它们的引用以以不同的方式实现类似的目标。)

    【讨论】:

      【解决方案4】:

      一个指针可以保存在多个变量中,将其中一个设置为 NULL 仍然会在其他变量中留下无效指针。所以你并没有真正获得多少,你更有可能创造一种虚假的安全感。

      除此之外,您还可以创建自己的函数来满足您的需求:

      template<typename T>
      void deleten(T *&ptr) {
        delete ptr;
        ptr = NULL;
      }
      

      【讨论】:

        【解决方案5】:

        因为实际上没有任何必要,而且因为它需要删除指针到指针,而不仅仅是指针。

        【讨论】:

        • true,但这会导致相同的开销
        【解决方案6】:

        delete 主要用于析构函数,在这种情况下将成员设置为 NULL 是没有意义的。几行之后,在结束时},该成员不再存在。在赋值运算符中,无论如何,删除后通常都会有一个赋值。

        此外,它会使以下代码非法:

        T* const foo = new T;
        delete foo;
        

        【讨论】:

          【解决方案7】:

          还有一个原因;假设 delete 确实将其参数设置为 NULL:

          int *foo = new int;
          int *bar = foo;
          delete foo;
          

          应该将 bar 设置为 NULL 吗?你能概括一下吗?

          【讨论】:

            【解决方案8】:

            如果您有一个指针数组,并且您的第二个操作是删除空数组,那么在即将释放内存时将每个值设置为 null 是没有意义的。如果你想让它为空.. 给它写空:)

            【讨论】:

              【解决方案9】:

              C++ 允许您定义自己的操作符 new 和 delete,以便它们使用您自己的池分配器。如果您这样做,则可以将 new 和 delete 用于不是严格地址但表示池数组中的索引的东西。在这种情况下,NULL (0) 的值可能具有法律意义(指池中的第一项)。
              因此,将 delete 设置为 NULL 自动为其参数并不总是具有以下含义 - 将值设置为无效值。无效值可能并不总是 NULL。

              【讨论】:

                【解决方案10】:

                C++ 的理念是“只有在使用时才付费”。我想它可以回答你的问题。

                此外,有时您可以拥有自己的堆来恢复已删除的内存.. 或者有时指针不属于任何变量。或存储在少数变量中的指针 - 可能只有其中一个变量为零。
                如您所见,它有很多问题和可能的问题。

                【讨论】:

                  【解决方案11】:

                  自动将指针设置为 NULL 并不能解决大多数指针使用不当的问题。它可以避免的唯一崩溃是如果您尝试将其删除两次。如果你在这样的指针上调用成员函数怎么办?它仍然会崩溃(假设它访问成员变量)。 C++ 不限制您在 NULL 指针上调用任何函数,从性能的角度来看也不应该这样做。

                  【讨论】:

                    【解决方案12】:

                    我看到人们对这个问题给出了奇怪的答案。

                    ptr = NULL; 这么简单的语句怎么会导致性能延迟?

                    另一个答案是我们可以有多个指针指向同一个 内存位置。我们当然可以。在这种情况下,对一个指针的删除操作只会使该指针为 NULL(如果 delete 使指针为 NULL),而另一个指针将是非 NULL 并指向空闲的内存位置。

                    解决方案应该是用户应该删除所有指向同一位置的指针。在内部,它应该检查内存是否已经释放而不是不释放。只将指针设为 NULL。

                    Stroustrup 可以设计删除以这种方式工作。他认为程序员会解决这个问题。所以他忽略了。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-04-19
                      • 2013-05-10
                      • 1970-01-01
                      • 2011-08-22
                      • 1970-01-01
                      相关资源
                      最近更新 更多