为什么unique_ptr有效,而auto_ptr不适用于STL
Why unique_ptr works but auto_ptr doesn’t with STL
我已经参考了许多关于这些问题的StackOverflow链接,其中auto_ptr
不能很好地使用STL的原因是std::auto_ptr<>
不满足复制可构造和可分配的要求(因为auto_ptr
有一个伪复制构造函数,它基本上转移了所有权(。
但是即使是unique_ptr
也没有复制构造函数和赋值运算符(它被禁用了(,那么如何满足可复制构造和可赋值的要求呢?
您正在向后看整个事情。
在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
仍然在撒谎,所以为了向后兼容性,我们创建了一种新的类型,它尊重新的语言功能,不会对人们撒谎。
我假设您指的是在STL容器中使用智能指针。
auto_ptr
可以使用,但不应该使用,因为它的复制构造函数可能会意外地移动数据(它是在C++11中添加带有右值引用的移动语义之前设计的(。
unique_ptr
没有复制构造函数,所以它不能在STL容器中简单地使用。复制指针的操作不起作用,但这是它安全的原因。您仍然可以显式地使用移动迭代器或模板将不可复制的元素放入容器中。
此处的容器中使用unique_ptr
的示例:那么unique_ptr可以在stl集合中安全使用吗?
auto_ptr看起来像是复制可构造/可赋值的,因为它有一个复制构造函数和赋值运算符。
问题是它的复制构造函数和赋值没有实现复制语义,而是实现移动语义。这使得auto_ptr的接口令人惊讶,并使其在内部分配元素的容器(如vector(中不可用。
更糟糕的是,在向量中使用auto_ptr格式良好(没有编译错误(,但没有有用的行为,这很容易导致未定义的行为(即严重错误(。
但即使unique_ptr也没有复制运算符和赋值运算符(已禁用(
unique_ptr不需要是可复制的或可赋值的。对于大多数用例来说,移动可构造和可分配就足够了。
unique_ptr可以取代auto_ptr的所有使用,并且不存在auto_ptr问题。自从C++11引入unique_ptr以及对移动的语言支持以来,auto_ptr一直被弃用,而自C++17以来,auto_pr已从标准库中删除。
- C++:在不中断共享的情况下通过引用传递共享 PTR?
- 为什么我不能在不进行任何转换的情况下将浮点数放入任何类型的 ptr 中?
- OpenGL/Glew C++纹理不适用
- 十进制到二进制的实现不能完全适用于我大学的检查器。问题或提示可能是什么
- 保证复制省略不应该适用吗?
- 当我在 windows7 中安装程序时,我指定的字体大小不适用
- C++:使用 shared_ptr<...> 而不是原始 ptr
- 使用程序集嵌入数据时"Undefined reference"错误,使用适用于窗口的 mingw-w64 编译(COFF 而不是 ELF)
- accelerator.cu(8): 错误:属性"managed"在这里不适用?
- OpenSSL:当输出ptr为空时,BIGNUM的bin2bn不会分配新的BIGNUM
- 为什么 std::vector 适用于类定义中的不完整类型?
- 为什么(常量字符*)ptr 不被视为左值
- typedef X=<T>T::UserType1,但如果不适用,typedef X<T>=UserType2
- 用C++编写一个程序,对一个简单的序列求和:1/N + 2/N-1 + 3/N-2+ ...不适用
- 为什么非常量ptr不能隐式地将ptr转换为常量作为模板中的参数
- SFINAE在这里不适用吗?
- 当是复制和交换习语不适用
- 在函数实参中使用模板形参不适用gcc4.8
- 为什么不使用空自动PTR不会终止程序?
- 为什么 *ptr++ 不更改 pointee 的值,但 (*ptr)++ 会更改?