为什么 unique_ptr 有效但 auto_ptr 不适用于 STL
Why unique_ptr works but auto_ptr doesn’t with STL
我参考了很多关于这些问题的 Whosebug 链接,其中 auto_ptr
不能很好地使用 STL 的原因是
std::auto_ptr<>
不满足可复制构造和可分配的要求(因为 auto_ptr
有一个伪造的复制构造函数,它基本上转移了所有权)。
但即使unique_ptr
也没有复制构造函数和赋值运算符(它被禁用),那么如何满足可复制构造和可赋值的要求?
我假设您指的是在 STL 容器中使用智能指针。
auto_ptr
可以,但是不应该使用,因为它的复制构造函数可能会意外移动数据(它是在C中添加具有右值引用的移动语义之前设计的++11)。
unique_ptr
没有复制构造函数,因此不能在 STL 容器中简单使用。复制指针的操作将不起作用,但这就是安全的原因。您仍然可以显式使用 move iterators 或 emplace 将不可复制的元素放入容器中。
在此处的容器中使用 unique_ptr
的示例:
So can unique_ptr be used safely in stl collections?
你在倒着看整个事情。
在 C++98/03 中,我们得到 auto_ptr
。这种类型通过假装它支持复制语义来欺骗所有人,而实际上复制它所做的事情与复制操作非常不同。因此,任何依赖于提供复制语义的类型的类型,如某些容器,都不会很好地获得 auto_ptr
。当然,您只会在您的代码出现功能障碍时发现,而不是在编译时发现。
在 C++11 中,我们得到了 unique_ptr
,一种明确不提供复制语义的类型。相反,它提供了移动语义,并正确地提供了它们。因此,任何依赖于提供复制语义的类型的类型在给定 unique_ptr
.
时都将无法编译。
然而,之所以会出现unique_ptr
,完全是因为在C++11的语言中加入了移动对象的概念。当新概念被添加到语言中时,现有工具(如标准库要求)通常会根据该语言功能重新评估。
例如,以前需要复制语义的类型不一定必须保留该要求。需要复制语义的 C++98/03 容器在 C++11 中更新为仅需要 (noexcept) 从类型移动语义。
所以并不是 unique_ptr
满足了 auto_ptr
没有满足的某些要求。就是语言改变了不再需要那个要求,但是 auto_ptr
仍然在谎言它做了什么,所以为了向后兼容,我们创建了一个尊重新语言特性并且不欺骗人们的新类型.
auto_ptr 看起来像复制构造/可分配的,因为它有一个复制构造函数和赋值运算符。
问题是它的复制构造函数和赋值没有实现复制语义,而是实现了移动语义。这使得 auto_ptr 的接口令人惊讶,并使其在内部分配元素的容器(如 vector)中无法使用。
更糟糕的是,在向量中使用 auto_ptr 是格式正确的(没有编译错误),但没有有用的行为,这很容易导致未定义的行为(即严重的错误) .
But even unique_ptr doesn't have copy ctor and assignment operator(its disabled)
unique_ptr 不需要可复制构造或可分配。对于大多数用例来说,移动可构造和可分配就足够了。
unique_ptr可以替代auto_ptr的所有用法,不存在auto_ptr的问题。自从 C++11 引入了 unique_ptr 以及对移动的语言支持后,auto_ptr 已被弃用,自 C++17 以来,auto_ptr 已从标准库中删除。
我参考了很多关于这些问题的 Whosebug 链接,其中 auto_ptr
不能很好地使用 STL 的原因是
std::auto_ptr<>
不满足可复制构造和可分配的要求(因为 auto_ptr
有一个伪造的复制构造函数,它基本上转移了所有权)。
但即使unique_ptr
也没有复制构造函数和赋值运算符(它被禁用),那么如何满足可复制构造和可赋值的要求?
我假设您指的是在 STL 容器中使用智能指针。
auto_ptr
可以,但是不应该使用,因为它的复制构造函数可能会意外移动数据(它是在C中添加具有右值引用的移动语义之前设计的++11)。
unique_ptr
没有复制构造函数,因此不能在 STL 容器中简单使用。复制指针的操作将不起作用,但这就是安全的原因。您仍然可以显式使用 move iterators 或 emplace 将不可复制的元素放入容器中。
在此处的容器中使用 unique_ptr
的示例:
So can unique_ptr be used safely in stl collections?
你在倒着看整个事情。
在 C++98/03 中,我们得到 auto_ptr
。这种类型通过假装它支持复制语义来欺骗所有人,而实际上复制它所做的事情与复制操作非常不同。因此,任何依赖于提供复制语义的类型的类型,如某些容器,都不会很好地获得 auto_ptr
。当然,您只会在您的代码出现功能障碍时发现,而不是在编译时发现。
在 C++11 中,我们得到了 unique_ptr
,一种明确不提供复制语义的类型。相反,它提供了移动语义,并正确地提供了它们。因此,任何依赖于提供复制语义的类型的类型在给定 unique_ptr
.
然而,之所以会出现unique_ptr
,完全是因为在C++11的语言中加入了移动对象的概念。当新概念被添加到语言中时,现有工具(如标准库要求)通常会根据该语言功能重新评估。
例如,以前需要复制语义的类型不一定必须保留该要求。需要复制语义的 C++98/03 容器在 C++11 中更新为仅需要 (noexcept) 从类型移动语义。
所以并不是 unique_ptr
满足了 auto_ptr
没有满足的某些要求。就是语言改变了不再需要那个要求,但是 auto_ptr
仍然在谎言它做了什么,所以为了向后兼容,我们创建了一个尊重新语言特性并且不欺骗人们的新类型.
auto_ptr 看起来像复制构造/可分配的,因为它有一个复制构造函数和赋值运算符。
问题是它的复制构造函数和赋值没有实现复制语义,而是实现了移动语义。这使得 auto_ptr 的接口令人惊讶,并使其在内部分配元素的容器(如 vector)中无法使用。
更糟糕的是,在向量中使用 auto_ptr 是格式正确的(没有编译错误),但没有有用的行为,这很容易导致未定义的行为(即严重的错误) .
But even unique_ptr doesn't have copy ctor and assignment operator(its disabled)
unique_ptr 不需要可复制构造或可分配。对于大多数用例来说,移动可构造和可分配就足够了。
unique_ptr可以替代auto_ptr的所有用法,不存在auto_ptr的问题。自从 C++11 引入了 unique_ptr 以及对移动的语言支持后,auto_ptr 已被弃用,自 C++17 以来,auto_ptr 已从标准库中删除。