我想知道为什么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>
。pstr2
和pstr3
指向内存中的同一个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));