为什么unique_ptr有效,但auto_ptr不适用于STL

问题描述 投票:0回答:3

我在这些问题上提到了很多StackOverflow链接,其中auto_ptr不能与STL一起工作的原因是std::auto_ptr<>不满足可复制构造和可分配的要求(因为auto_ptr具有伪造的复制构造函数,基本上可以转移所有权)。

但是即使unique_ptr也没有复制ctor和赋值运算符(已禁用),那么如何满足可复制构造和可赋值的要求?

c++ stl copy-constructor unique-ptr auto-ptr
3个回答
5
投票

您正在反向查看整个内容。

在C ++ 98/03中,我们得到了auto_ptr。这种类型对每个人来说都是假装它支持复制语义,而实际上复制它所做的事情与复制操作非常不同。因此,任何依赖于提供复制语义的类型的类型(例如某些容器)都不会很好地获得auto_ptr。当然,您只会发现代码何时无法正常工作,而不会在编译时发现。

在C ++ 11中,我们得到了unique_ptr,该类型明确不提供复制语义。而是提供了移动语义,并正确提供了它们。因此,在给定unique_ptr时,任何依赖提供复制语义的类型的类型都将无法编译。

但是],之所以成为unique_ptr的原因,完全是因为在C ++ 11中将移动对象的概念添加到了语言中。当将新概念添加到该语言时,通常会相对于该语言功能重新评估现有工具,例如标准库要求。

例如,以前需要复制语义的类型不一定必须保持该要求。需要复制语义的C ++ 98/03容器在C ++ 11中进行了更新,仅要求(无例外)从类型中移动语义。

因此,并不是unique_ptr满足了auto_ptr不满足的某些要求。是因为语言已更改为不再需要该要求,但auto_ptr仍在说明其作用,因此出于向后兼容的考虑,我们创建了一种尊重新语言功能并且不对人撒谎的新类型。 >

我假设您是指将智能指针与STL容器一起使用。

可以使用

auto_ptr,但不应该

,因为其副本构造函数可能会意外移动数据(它是在C ++ 11中添加带有右值引用的移动语义之前设计的)。

unique_ptr没有副本构造函数,因此不能在STL容器中简单使用。复制指针的操作将不起作用,但这就是确保它安全的原因。您仍然可以显式使用move iterators或emplace将不可复制的元素放入容器。

此处在容器中使用unique_ptr的示例:So can unique_ptr be used safely in stl collections?

auto_ptr看起来像可复制构造/可分配复制,因为它具有复制构造函数和赋值运算符。

问题在于其副本构造函数和赋值未实现副本语义,而是移动了语义。这使auto_ptr的接口令人惊讶,并使其在内部分配元素的容器(例如vector)中不可用。

更糟糕的是,在向量中使用auto_ptr格式正确(没有编译错误),但没有有用的行为,这很容易导致未定义的行为(即严重的错误)。

但是即使unique_ptr也没有复制ctor和赋值运算符(已禁用)

unique_ptr不需要是可复制构造的或可分配的。对于大多数用例而言,可以进行构造和分配是足够的。

unique_ptr可以替代auto_ptr的所有用法,并且没有auto_ptr的问题。自从引入了unique_ptr以及用于移动的语言支持的C ++ 11以来,auto_ptr被弃用,自C ++ 17起,auto_ptr已从标准库中删除。


1
投票

我假设您是指将智能指针与STL容器一起使用。

可以使用

auto_ptr,但不应该


1
投票

auto_ptr看起来像可复制构造/可分配复制,因为它具有复制构造函数和赋值运算符。

问题在于其副本构造函数和赋值未实现副本语义,而是移动了语义。这使auto_ptr的接口令人惊讶,并使其在内部分配元素的容器(例如vector)中不可用。

© www.soinside.com 2019 - 2024. All rights reserved.