C++ 0x unique_ptr误会?

tow*_*owi 2 c++ unique-ptr c++11

N2812中引言中的一个例子,其中a unique_ptr作为值参数给出

void push_back2(
  std::list<std::unique_ptr<int>>& l, std::unique_ptr<int> a)
{
  l.push_back(a); // oops: moves from the lvalue 'a', silently!
  l.push_back(a); // oops: 'a' no longer has its original value
}
Run Code Online (Sandbox Code Playgroud)

本文讨论了RValue/LValue重载分辨率的问题,但这不是我的观点.

我想知道,如果提供参数std::unique_ptr<int> a by-value不会导致编译器错误?它会复制它,对吗?这是不允许unique_ptr

我知道这篇论文很老了,也许这个定义unique_ptr已经改变了.但也许这只是一个错字,而作者想要写作std::unique_ptr<int> &a呢?

我的gcc 4.7.0与我同意,但那没有证据:-)

void push_back2( std::list<std::unique_ptr<int>>&, std::unique_ptr<int> ) { };
int main() {
  list<unique_ptr<int>> lst;
  unique_ptr<int> num { new int{4} };
  push_back2(lst, num); //ERR: use of deleted function
}
Run Code Online (Sandbox Code Playgroud)

tem*_*def 9

按值获取参数没有任何问题.您是正确的,如果您尝试使用副本初始化参数,您将收到编译器错误,因为该函数已被删除.但是,您可以通过提供rvalue作为参数来初始化value参数.例如:

std::unique_ptr<int> myPtr{ /* ... */ }
std::list<std::unique_ptr<int>> elems;
push_back2(elems, myPtr);            // Error, as you've noted
push_back2(elems, std::move(myPtr)); // Fine, uses move constructor to initialize
Run Code Online (Sandbox Code Playgroud)

这种语法很好,因为它会强制您明确指示您将指针移交给函数.

一旦你进入push_back2,你是正确的,push_back将无法接受,unique_ptr因为它将尝试使用不存在的复制构造函数.要解决此问题,您需要std::move再次使用:

void push_back2(
  std::list<std::unique_ptr<int>>& l, std::unique_ptr<int> a)
{
  l.push_back(std::move(a)); // Fine, moves a
  l.push_back(std::move(a)); // Well that was dumb, but you asked for it!
}
Run Code Online (Sandbox Code Playgroud)

我希望我正确地解释你的问题,这就是你正在寻找的......让我知道,如果还有什么我可以尝试澄清的!