【问题标题】:Advantages/disadvantages of auto pointers自动指针的优点/缺点
【发布时间】:2011-01-07 05:08:06
【问题描述】:

与普通指针相比,使用自动指针(auto_ptr)有哪些优点和缺点?听说会自动释放内存,怎么不经常用呢?

【问题讨论】:

  • 注意:std::auto_ptr 只是 C++ 中使用的一整套智能指针之一。
  • 好的。我现在更好地理解你的问题。是的 std::auto::ptr 是最少使用的,但你不应该孤立地看待它们。它们是智能指针集的一部分,并且有自己的特定用途。 std::auto_ptr 的一个很好的用途是所有权转移的文档。

标签: c++ smart-pointers


【解决方案1】:

std::auto_ptr 的主要缺点是它具有 transfer-of-ownership 语义。这使得无法将std::auto_ptr 存储在 STL 容器中,因为容器在您存储或获取元素时使用复制构造函数。

另外,我注意到std::auto_ptr 的另一个重要方面是它们不能用于PIMPL 成语的使用。这是因为,它们需要包装类的析构函数的完整定义。有关详细讨论,请参阅 c.l.c++.m 上的 this 线程。

更新:所有权转让

class Test {};
std::auto_ptr<Test> ap_test_1(new Test);
std::auto_ptr<Test> ap_test_2(new Test);

ap_test_2 = ap_test_1;  // here ap_test_1's ownership is transferred i.e. ap_test_2 is the 
                        // new owner and ap_test_1 is NULL.

请参阅 Herb Sutter 网站上的 this 线程,了解有关在 STL 算法使用的 STL 容器中使用这意味着什么的更多详细信息。

【讨论】:

  • 是的,我想这会回答我的问题,但您能详细解释一下这种所有权转让吗?
  • auto_ptr 可以用于pimpl;这不是特别好,因为您必须声明和实现析构函数。最好使用不需要 dtor 定义的 boost::scoped_ptr(或 shared_ptr)。
  • 在 PIMPL 中使用 std::auto_ptr 没有问题。
  • @Martin:那么你需要提供你包装的类的完整定义。 PIMPL 在许多项目中的主要目的是实现编译器防火墙/隐藏实现。在这种情况下,您不能包含该类的标头,它必须仅在前向声明中起作用。这对于 std::auto_ptr 是不可能的,详细讨论请参见 c.l.c++.m 线程。
  • @MattyT:我认为 boost::scoped_ptr 也需要定义类 dtor。由于 boost::shared_ptr 允许自定义删除器,因此不需要。
【解决方案2】:

智能指针在 C++ 中经常使用,尽管可能没有应有的那么频繁。 std::auto_ptr 有一些问题(例如,您不能在标准库集合中使用它),但还有很多其他问题。其中最受欢迎的是the ones that come with the Boost library,它将成为下一个 C++ 标准的一部分 - 你应该看看。

请注意,智能指针主要与所有权有关,并删除动态创建的对象。如果您没有动态创建的对象,则通常不需要智能指针:

{
  int i = 42;
  auto_ptr <int> p( & i );   // bad!
}

你真的不想这样做,因为当自动指针超出范围时,它会尝试删除 i。不幸的是,我不是动态创建的,所以会发生不好的事情。因此,在大多数 C++ 程序中,您需要两种类型的指针,智能指针和普通指针。

【讨论】:

  • 是的,我从 Boost 那里听说过。只是我特别关心的是它没有像使用普通指针那样频繁使用的原因。
  • auto_ptr 不经常使用,因为在大多数情况下,来自 Boost 的那些更可取。智能指针经常使用,至少在许多程序员中,比普通指针更常用。为什么你认为普通指针更常用?
  • @jasonline:在现代 C++ 代码中,我几乎看不到普通指针。智能指针是常态,普通指针是非常例外的。如果您看到任何带有指针的代码,请对作者非常怀疑。我唯一一次在演示代码中看到普通(RAW)指针是教学生什么是指针的教程。
  • @jalf:根据我的经验...我更经常看到智能指针和普通指针,但从来没有看到自动指针。我期待智能指针和自动指针,所以我问自动指针有什么不好。
  • @Martin York:谢谢,我知道智能指针更受欢迎。
【解决方案3】:

不要将自动指针 (std::auto_ptr) 与智能指针系列(尤其是 std::auto_ptr、boost::scoped_ptr 和 boost::shared_ptr)混淆。

我几乎从不使用自动指针,因为大多数时候,我宁愿使用引用。我做的唯一一次是在对象的构造函数中无法实例化的成员变量。

相反,智能指针非常强大,但这不是你的问题,我猜 :)

【讨论】:

    【解决方案4】:

    优点是使用简单,他们做他们的工作。

    void foo() {
      std::auto_ptr<int> bar(new int);
      // do the stuff that potentially throw
    
    } // the auto_ptr destructor will call delete here 
    

    缺点是一旦你摆脱这种简单的使用,你就会遇到 auto_ptr 的坏语义。

    std::auto_ptr<int> foo(new int);
    std::auto_ptr<int> bar = foo;    // foo is changed here! It does not have ownership anymore.
    

    你最好使用unique_ptr和shared_ptr,它们语义很好,在boost::中可用,在下一个C++标准中将在std::中可用

    【讨论】:

      【解决方案5】:

      也许是它没有被广泛使用的最大原因:

      std::auto_ptr 有一个巨大的缺点:它不能在不破坏的情况下被复制。当您需要复制自动指针时,原始实例将被销毁。这意味着您在任何时候都可能只有一个对象副本。这也意味着 auto_ptr 不能与标准容器一起使用,例如 vector、deque、list、set 和 map。事实上,它几乎不能用于任何依赖复制构造的类。

      此外,auto_ptr 并不安全,因为没有什么可以阻止您意外地进行复制。如果你这样做,你会破坏原始副本。此外,一些不太符合标准的 C++ 编译器允许您将声明的对象存储在 auto_ptr 中,并在不包含类的完整定义的情况下使用它。这总是会导致内存泄漏。

      【讨论】:

        【解决方案6】:

        auto_ptr 存在的主要理由是以异常安全的方式转移所有权。尽管大多数人将其用作穷人的 boost::scoped_ptr。

        主要用于使用对象指针作为参数或返回值返回的函数。

        例如一个工厂函数

        std::auto_ptr<MyClass> createMyClass(MyClass::Type type) {
            if (type == MyClass::TypeOne) {
                return std::auto_ptr(new MyClassOne);
            }
            else {
                return std::auto_ptr(new MyClassTwo);
           }
        }
        
        
        void foo() {
            std::auto_ptr<MyClass> myc = createMyClass(MyClass::TypeOne);
        
            // use myc
        }
        

        虽然这段代码非常简单,并且如果抛出异常则不应抛出异常 myc 正确处理它,但使用原始指针执行此操作会很困难。

        boost::shared_ptr 也可以使用,但这提供了比所需更多的功能,它还表明您希望共享对象。使用 auto_ptr 更简单,并且您清楚地表明您正在转移所有权。

        最近有人告诉我 boost::unique_ptr 的用法似乎与 auto_ptr 相同,但没有缺点。

        查看best practice when returning smart pointers了解更多信息

        【讨论】:

          【解决方案7】:

          auto_ptr 具有它指向的对象的所有权模型。您不能对同一个对象有多个引用,也不能将它们放在 stl 容器等中 - 看起来确实是在转移所有权的代码,并且会在生产中导致令人讨厌的难以追踪的错误。

          boost 的shared_ptr 在几乎所有情况下都更加实用。

          【讨论】:

          • 如果使用正确,为什么会导致难以追踪问题。 std::auto_ptr 完全按照它的意图去做(不多不少)。 std::tr1::shared_ptr 是一种完全不同类型的智能指针。学习使用正确类型的智能指针。
          • 我希望你永远不会有错误,马丁 :)
          【解决方案8】:

          小故事:std::auto_ptr 不能共享,常规指针可以。

          然后是Boost.SmartPointer

          【讨论】:

            【解决方案9】:

            auto_ptr 可以是used for multiple purposes,但我认为最好的用途是在堆上分配对象并在退出范围堆栈帧时释放它们。

            恕我直言,auto_ptr 的唯一真正问题是名称。人们看着它并认为它是一个智能指针,当然不是。

            如果我们将其称为AutoDelete&lt;T&gt; 之类的名称,也许我们会进行不同类型的讨论。 :-)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-09-23
              • 1970-01-01
              • 2018-08-16
              • 2011-04-11
              • 2011-06-19
              相关资源
              最近更新 更多