std::move和unique_ptr::release之间有什么区别



我想知道为什么pstr2在STDOUT的第4行不为空。AFAIK,移动和释放在呼叫后没有所有权。

auto pstr = make_unique<string>(5, '*');
cout << (pstr ? *pstr : "pstr is empty") << endl;
auto pstr2(pstr.release());
cout << (pstr ? *pstr : "pstr is empty") << endl;
cout << (pstr2 ? *pstr2 : "pstr2 is empty") << endl;
auto pstr3(move(pstr2));
cout << (pstr2 ? *pstr2 : "pstr2 is empty") << endl;
cout << (pstr3 ? *pstr3 : "pstr3 is empty") << endl;

输出为

*****
pstr is empty
*****
***** <-- my curious part.
*****

我认为您假设pstr.release()返回std::unique_ptr,而在编写的代码中,它返回std::string *。由于无法从中移出,因此可以解释您得到的结果。

如果您更改:

auto pstr2(pstr.release());

至:

auto pstr2 = unique_ptr<string>(pstr.release());

然后你会得到你期望的结果。

现场演示

当您将变量的类型声明为auto时,它的实际类型是根据初始化期间分配给该变量的任何值推导出来的。

pstr的类型被推导为unique_ptr<string>,因为这是make_unique<string>(5, '*')返回的。

auto pstr2(pstr.release());不会做你认为它会做的事。release()不会像您预期的那样返回unique_ptr<string>。它返回由pstr保持的原始string*指针。因此,pstr2的类型被推导为string*,而不是unique_ptr<string>(由于pstr已经放弃了对其string*指针的所有权,因此在完成后需要显式调用delete pstr2;,否则string对象将被泄露(。

auto pstr3(move(pstr2));类似。由于pstr2是原始string*,而std::move()只是原始指针的副本,因此pstr3的类型也被推导为string*,而不是unique_ptr<string>pstr2pstr3指向内存中的同一个string对象,这就是为什么它们都不为空,并且都向控制台输出相同的数据。

如果您更改pstr2的类型,将auto显式地替换为unique_ptr<string>(或decltype(pstr)(,那么您将得到您期望的行为,例如:

auto pstr = make_unique<string>(5, '*');
cout << (pstr ? *pstr : "pstr is empty") << endl;
unique_ptr<string> pstr2(pstr.release());
// or: decltype(pstr) pstr2(pstr.release());
cout << (pstr ? *pstr : "pstr is empty") << endl;
cout << (pstr2 ? *pstr2 : "pstr2 is empty") << endl;
auto pstr3(move(pstr2));
// or: decltype(pstr2) pstr3(move(pstr2));
cout << (pstr2 ? *pstr2 : "pstr2 is empty") << endl;
cout << (pstr3 ? *pstr3 : "pstr3 is empty") << endl;

输出

*****pstr为空*****pstr2为空*****

实时演示

因为pstr.release((返回一个原始指针,所以pstr2&pstr3作为原始指针进行重复数据消除。

编译后,它们就像

unique_ptr<string> pstr = make_unique<string>(5, '*');
string* pstr2(pstr.release());
string* pstr3(move(pstr2));

相关内容

  • 没有找到相关文章

最新更新