简体   繁体   English

std::move 和 unique_ptr::release 有什么区别?

[英]What is the difference between std::move and unique_ptr::release?

I am wondering why pstr2 is not null at the 4th line of STDOUT.我想知道为什么 pstr2 在 STDOUT 的第 4 行不是 null。 AFAIK, move and release do not have ownership after a call. 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;

The output is output 是

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

When you declare a variable as auto for its type, its actual type is deduced from whatever value is assigned to the variable during its initialization.当您将变量声明为其类型的auto时,其实际类型是从在其初始化期间分配给该变量的任何值推导出来的。

The type of pstr is deduced as unique_ptr<string> , because that is what make_unique<string>(5, '*') returns. pstr的类型被推断为unique_ptr<string> ,因为那是make_unique<string>(5, '*')返回的内容。

auto pstr2(pstr.release()); does not do what you think it does.不做你认为它做的事。 release() does not return a unique_ptr<string> , like you are expecting. release()不会像您期望的那样返回unique_ptr<string> It returns the raw string* pointer that was being held by pstr .它返回pstr持有的原始string*指针。 So, the type of pstr2 is deduced as string* , not as unique_ptr<string> (and since pstr has given up its ownership of its string* pointer, you need to explicitly call delete pstr2; when you are done, or else the string object will be leaked).因此, pstr2的类型被推断为string* ,而不是unique_ptr<string> (并且由于pstr已经放弃了对其string*指针的所有权,因此您需要显式调用delete pstr2;完成后,否则string object 会泄露)。

Similar with auto pstr3(move(pstr2));类似于auto pstr3(move(pstr2)); . . Since pstr2 is a raw string* , and std::move() is just a copy for a raw pointer, the type of pstr3 is also deduced as string* , not as unique_ptr<string> .由于pstr2是原始string* ,而std::move()只是原始指针的副本,因此pstr3的类型也被推断为string* ,而不是unique_ptr<string> pstr2 and pstr3 are pointing at the same string object in memory, which is why neither of them are null, and both output the same data to the console. pstr2 and pstr3 are pointing at the same string object in memory, which is why neither of them are null, and both output the same data to the console.

If you change the type of pstr2 to replace the auto with unique_ptr<string> explicitly (or decltype(pstr) ), then you will get the behavior you are expecting, eg:如果您更改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;

Output Output

*****
pstr is empty
*****
pstr2 is empty
*****

Live Demo现场演示

I think you are assuming that pstr.release() returns a std::unique_ptr whereas in the code as written it returns a std::string * .我认为您假设pstr.release()返回一个std::unique_ptr而在编写的代码中它返回一个std::string * Since this cannot be moved from, this explains the results you get.由于这不能被移动,这解释了你得到的结果。

If you change:如果你改变:

auto pstr2(pstr.release());

to:至:

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

then you get the results you expect.然后你会得到你期望的结果。

Live demo现场演示

Because pstr.release() returns a raw pointer, then pstr2 & pstr3 are deducated as raw pointers.因为 pstr.release() 返回一个原始指针,所以 pstr2 和 pstr3 被推导出为原始指针。

After compiling they are just like编译后它们就像

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM