与普通指针相比,使用自动指针(auto_ptr)有哪些优缺点?我听说它会自动释放内存,但为什么不经常使用?
答案 0 :(得分:10)
std::auto_ptr
的主要缺点是它具有所有权转移语义。这使得无法将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容器中使用时的含义的详细信息。
答案 1 :(得分:6)
智能指针 经常在C ++中使用,但可能并不像它们应该的那样频繁。 std::auto_ptr
有一些问题(例如,您无法在标准库集合中使用它),但还有许多其他问题。其中最受欢迎的是the ones that come with the Boost library,它将成为下一个C ++标准的一部分 - 你应该看看。
请注意,智能指针主要是关于所有权,以及删除动态创建的对象。如果您没有动态创建的对象,通常不需要智能指针:
{
int i = 42;
auto_ptr <int> p( & i ); // bad!
}
你真的不想这样做,因为当autopointer超出范围时,它会尝试删除i。不幸的是,我不是动态创建的,所以会发生不好的事情。因此,在大多数C ++程序中,您需要两种指针,智能和正常。
答案 2 :(得分:1)
不要将自动指针(std :: auto_ptr)与智能指针系列混淆(特别是std :: auto_ptr,boost :: scoped_ptr和boost :: shared_ptr)。
我几乎从不使用自动指针,因为在大多数情况下,我宁愿使用引用。我这样做的唯一时间是无法在对象的构造函数中实例化的成员变量。
相反,智能指针非常强大,但这不是你的问题,我想:)
答案 3 :(得分:1)
优点是,为了简单使用,他们可以完成自己的工作。
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 ::中使用
答案 4 :(得分:1)
也许是它没有被广泛使用的最大原因:
std :: auto_ptr有一个巨大的缺点:没有破坏就无法复制它。当您需要复制自动指针时,原始实例将被销毁。这意味着您可以随时拥有该对象的单个副本。这也意味着auto_ptr不能与标准容器一起使用,例如vector,deque,list,set和map。事实上,它几乎不能用于任何依赖复制构造的类。
此外,auto_ptr不安全,因为没有什么能阻止您意外地复制。如果你这样做,你会破坏原始副本。此外,一些不太符合标准的C ++编译器允许您在auto_ptr中存储前向声明的对象,并使用它而不包括类的完整定义。这总是会导致内存泄漏。
答案 5 :(得分:1)
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具有相同的用法而没有缺点。
答案 6 :(得分:0)
auto_ptr具有其指向的对象的所有权模型。你不能对同一个对象有多个引用,并且你不能把它们放在stl容器中这样 - 看起来像它的代码实际上是转移所有权,并且会在生产中引起令人讨厌的难以追踪的错误。 / p>
boost shared_ptr几乎在所有情况下都更加实用。
答案 7 :(得分:0)
短篇小说:std :: auto_ptr无法共享,常规指针可以。
答案 8 :(得分:0)
auto_ptr
可以是used for multiple purposes,但我认为最好的用途是在堆上分配对象并在退出范围堆栈框架时释放它们。
恕我直言auto_ptr
唯一的真正问题是名称。人们看着它并认为它是一个智能指针,当然它不是。
如果我们称它为AutoDelete<T>
,或许我们会进行不同类型的讨论。 : - )