C++11标准库是否提供将std::shared_ptr
转换为std::unique_ptr
,或者将std::unique_ptr
转换为std::shared_ptr
的实用工具?这个操作安全吗?
C++11标准库是否提供将std::shared_ptr
转换为std::unique_ptr
,或者将std::unique_ptr
转换为std::shared_ptr
的实用工具?这个操作安全吗?
std::unique_ptr
是C++11表达独占所有权的一种方式,但它最有吸引力的特点之一是可以轻松高效地转换为std::shared_ptr
。这是
std::unique_ptr
非常适合作为工厂函数返回类型的关键部分。工厂函数无法知道调用者是否希望对他们返回的对象使用独占所有权语义,还是共享所有权(即std::shared_ptr
)更适合。通过返回std::unique_ptr
,工厂为调用者提供了最有效的智能指针,但他们不会阻碍调用者将其替换为更灵活的“兄弟姐妹”。不允许将
std::shared_ptr
转换为std::unique_ptr
。一旦你将资源的生命周期管理委托给std::shared_ptr
,就无法改变主意。即使引用计数为1,也无法重新获得对资源的所有权,以便让std::unique_ptr
来管理它。参考:《Effective Modern C++》。42 SPECIFIC WAYS TO IMPROVE YOUR USE OF C++11 AND C++14。Scott Meyers。
简而言之,您可以轻松高效地将std::unique_ptr
转换为std::shared_ptr
,但不能将std::shared_ptr
转换为std::unique_ptr
。
例如:
std::unique_ptr<std::string> unique = std::make_unique<std::string>("test");
std::shared_ptr<std::string> shared = std::move(unique);
或:std::shared_ptr<std::string> shared = std::make_unique<std::string>("test");
std::unique_ptr
分配给std::shared_ptr
,编译器实际上不会阻止(甚至警告)。 - StefanQstd::unique_ptr
分配给 std::shared_ptr
吗?实际上,标准库定义了一个移动赋值运算符 template<class Y, class Deleter> shared_ptr& operator=(std::unique_ptr<Y, Deleter>&& r);
,用于将 std::unique_ptr
转换为 std::shared_ptr<T>
。 - cuddlebugCullerunique_ptr
到shared_ptr
的转换是有效的,因为shared_ptr
类了解unique_ptr
并且具有接受rvalue reference
的构造函数和赋值运算符(关键是rvalue reference
可以保证unique_ptr
不会再被使用)。这不是std::move
的功劳,而是shared_ptr
类的功劳。 - luca我更愿意这样做。
std::unique_ptr<int> up_ = std::make_unique<int>();
std::shared_ptr<int> sp_ = std::move(up_);
std::shared_ptr<std::string> shared = std::make_shared<std::string>("test");
std::unique_ptr<std::string> unique = std::make_unique<std::string>(std::move(*shared));
*shared
的内容(即由shared
指针管理的字符串)被移动到由unique
指针管理的新的std::string
实例中。这样做的副作用是,由shared
管理的std::string
对象处于“有效但未指定状态”,因为它已经被剥夺了其内容。但是,由于使受管理对象“唯一”的整个目的是防止它被其他任何地方访问,我认为这实际上是符合操作的精神的。#include <iostream>
#include <memory>
int main() {
std::unique_ptr<int> up;
{
std::shared_ptr<int> sp = std::shared_ptr<int>(new int (42),
[&up] (int* ptr) {up = std::unique_ptr<int>(ptr); });
}
std::cout << "Unique-ptr = " << *up << "\n";
}
std::shared_ptr<whatever> s_ptr(u_ptr.release());
std::shared_ptr<whatever> s_ptr(std::move(u_ptr));
- emlaistd::shared_ptr<whatever> s_ptr{std::move(u_ptr)};
。 - polyvertex
shared_ptr
没有任何关系。 - curiousguy