【问题标题】:AutoPointer with objects not allocated on heap具有未在堆上分配的对象的自动指针
【发布时间】:2012-05-23 23:15:28
【问题描述】:

一旦超出范围,自动指针在其指向的对象上内部调用 delete。如果我们分配一个在堆上创建的对象,这可以正常工作。但是,如果我尝试分配一个不是在堆上创建的对象,它会崩溃,因为 delete 被调用了两次。首先是 auto_ptr 本身,其次是当对象超出范围时,它的析构函数被再次调用。 如下图,

#include <iostream>
#include <memory>

using namespace std;

class sample
{
      public:
             sample() { puts("sample"); }
             ~sample() { puts("~sample"); }
};

int main()
{
    sample sObj;
    auto_ptr<sample> samplePtr(&sObj);
}

这是否意味着我们可以使用 auto_ptr 仅保存在堆上创建的对象?

【问题讨论】:

  • 您基本上是对的,但更好的办法是不要使用auto_ptr(而是使用unique_ptrshared_ptr 等):它已被证明是错误的来源,在新版本中已被弃用标准。
  • 为什么要将堆栈对象存储在auto_ptr 中?像auto_ptr 这样的智能指针类的全部意义在于它们最终删除了自己拥有的对象......
  • @Vlad,unique_ptr 是更好的通用替代品,仅在需要时才使用 shared_ptr。
  • 因为 delete 被调用了两次而崩溃 不,它崩溃是因为 auto_ptr 试图在一个不是使用 new 分配的指针上的 delete,而不是因为 double删除。
  • @RajeevMehta:是的,但您需要了解调用析构函数和delete 之间存在区别。当堆栈上分配的对象超出范围时,将调用其析构函数,但不是通过deletedelete 仅针对使用 new 分配的内存调用。

标签: c++


【解决方案1】:

是的,确切地说,您只能将auto_ptr 用于堆分配的对象。技术原因是 auto_ptr 析构函数调用 delete 并在未分配在堆上的对象上调用 delete未定义的行为,这可能会使堆崩溃,多次运行析构函数,以及其他任何你不应该的事情不要指望也不应该推测。

【讨论】:

    【解决方案2】:

    简短的回答 - 是的。

    这意味着您将管理内存的责任交给auto_ptr。但是,如果您在自动存储中创建对象,则该责任在于运行时,因此您不能放弃。

    【讨论】:

      【解决方案3】:

      自动存储持续时间的对象(您所谓的“在堆栈上”)会自动清理。 auto_ptr 的存在是为了便于清理用new 分配的对象(它在指针上调用delete)。将auto_ptr 与自动存储持续时间的对象一起使用是没有意义的,因为它们没有分配给new

      【讨论】:

        【解决方案4】:

        如果你使用 std::auto_ptr 你只能保存在堆上创建的对象。

        但是如果你使用例如 boost::shared_ptr 你可以指定一个删除器,它将 当对象离开作用域时被调用。因此,如果您引用堆栈上的对象,您可以 使用实际上什么都不做的自定义删除器。
        详情见boost::shared_ptr

        std::auto_ptr 自 C++11 起已弃用
        C++11 std::auto_ptr deprecated

        【讨论】:

          【解决方案5】:

          这是否意味着我们可以使用auto_ptr 仅保存在堆上创建的对象?
          是的。
          自动对象会自动销毁,因此它们不需要像智能指针这样的包装器。

          请注意,您可以使用shared_ptrunique_ptr,这使您可以调用自定义删除函数。通过使用此自定义删除器功能,您可以使用自定义内存分配器而不是 new

          auto_ptr 已弃用,C++ 标准建议 unique_ptr 是更好的选择。

          【讨论】:

          • 您的意思是shared_ptrunique_ptr 用于分配在堆上的对象(以前使用auto_ptr),对吗?而不是自动存储中的对象。
          猜你喜欢
          • 2015-06-07
          • 2020-01-30
          • 2017-12-06
          • 2020-07-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-02-05
          • 2020-12-30
          相关资源
          最近更新 更多