编译但失败的C++std::vector<std::auto_ptr<T>>示例
什么是一个简单的 C++ 程序,其中 astd::vector<std::auto_ptr<T>>
编译但无法正确执行,而同一程序std::vector<std::unique_ptr<T>>
编译并正常工作,对于某些数据类型T
?
我知道这std::auto_ptr
已被弃用或删除;我只是想,涉及集装箱激励一个例子,为什么它被废弃或删除。
我g++-10 -std=c++20
在 MacOS Big Sur 版本 11.2.1 上使用。
回答
std::auto_ptr
根本不能在标准容器中使用。在这种情况下,它不会保持正确的语义。这就是移动语义std::unique_ptr
最初是在 C++11 中发明的原因之一。 std::auto_ptr
在 C++11 中被弃用,并在 C++17 中完全删除。所以不要在现代编码中使用它。
官方std::auto_ptr
弃用原因如下:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1856.html#20.4.5%20-%20Class%20template%20auto_ptr
给出的示例std::sort()
在 a 上使用std::vector<std::auto_ptr<int>>
:
通过这样的设计,可以将 auto_ptr 放入容器中:
vector<auto_ptr<int> > vec;
然而,这种设计的现场经验揭示了一些微妙的问题。即:
sort(vec.begin(), vec.end(), indirect_less());
根据 的实现
sort
,上面这行看起来合理的代码可能会也可能不会按预期执行,甚至可能会崩溃!问题是一些实现sort
会从序列中挑选一个元素,并存储它的本地副本。... value_type pivot_element = *mid_point; ...
该算法假设在这种构造之后
pivot_element
和*mid_point
是等价的。然而,当value_type
结果是 时auto_ptr
,这个假设失败了,随后算法也失败了。解决此问题的方法是
auto_ptr
通过禁止从const auto_ptr
. 使用这样的auto_ptr
,如果您尝试将其放入容器中,则会出现编译时错误。
最后的结论是这样的:
调用任何通用代码,无论是否对其
std
进行操作auto_ptr
都是有风险的,因为通用代码可能假设看起来像复制操作的东西实际上是复制操作。结论:
不应使用复制语法从左值移动。应改用其他移动语法。否则,通用代码可能会在需要复制时启动移动。
auto_ptr
使用复制语法从左值移动,因此从根本上是不安全的。
- The question is specifically asking for an example in which using of `std::auto_ptr` compiles but fails to execute correctly. It remains to be seen whether that's an appropriate question for SO or not. 🙂