C++0x unique_ptr 误解?

发布于 2024-11-30 16:57:00 字数 1090 浏览 2 评论 0原文

N2812 中是一个示例简介,其中将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
}

本文讨论了RValue/LValue重载的问题决议,但这不是我的观点。

我想知道是否提供参数 std::unique_ptra 按值 不会导致编译器错误? 它会复制它,对吗?对于 unique_ptr 来说这是不允许的

我知道这篇论文已经很旧了,也许从那以后 unique_ptr 的定义已经改变了。但也许这只是一个错字,作者想写成 std::unique_ptr;而是&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
}

In N2812 is an example in the Introduction where a unique_ptr is given as a value parameter

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
}

The paper discusses a problem with RValue/LValue overload resolution, but thats not my point.

I wonder, if providing the argument std::unique_ptr<int> a by-value is not causing a compiler error? It would copy it, right? And that is not allowed for unique_ptr

I am aware that the paper is quite old, maybe the definition of unique_ptr has changed, since. But maybe it's just a typo and the author wanted to write std::unique_ptr<int> &a instead?

My gcc 4.7.0 agrees with me, but thats no proof :-)

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
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

海夕 2024-12-07 16:57:00

按值获取参数没有任何问题。您是正确的,如果您尝试使用副本初始化参数,您将收到编译器错误,因为该函数已被删除。但是,您可以通过提供右值作为参数来初始化 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

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

一旦进入 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!
}

我希望我正确解释了您的问题,并且这就是您正在寻找的内容...如果有什么问题请告诉我否则我可以尝试澄清!

There's nothing wrong with taking the parameter by value. You are correct that if you try to initialize the parameter by using a copy, you will get a compiler error since that function is deleted. However, you could initialize the value parameter by providing an rvalue as the argument. For example:

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

This syntax is nice in that it forces you to explicitly indicate that you're handing the pointer over to the function.

Once you're inside push_back2, you are correct that push_back won't be able to take in the unique_ptr because it will try to use the nonexistent copy constructor. To fix this, you'll need to use std::move again:

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!
}

I hope that I interpreted your question correctly and that this is what you're looking for... let me know if there's anything else I can try to clarify!

时间你老了 2024-12-07 16:57:00

您对该行为的了解和假设是正确的。

该论文的示例令人困惑,因为它将两种语​​言混为一谈:带有概念的 C++ 和没有概念的 C++。在论文的假装语言中,需要 CopyConstructiblelist Push_back 被 SFINAE 去掉,只留下需要 MoveConstructible 的重载。在这样的 list 设计中,并且使用左值可以绑定到右值引用的旧规则,那么 push_back 将隐式移动来自 a 两次。

请注意,list 实际上以这种方式表现,我们在任何时候都不会遇到危险。作者只是试图设置一种情况,其中 const value_type&value_type&& 没有重载,并且您只有 value_type&& code> 在重载集中。

Your knowledge and assumptions about the behavior are correct.

The paper's example is confusing as it is conflating two languages: C++ with concepts and C++ without concepts. In the paper's pretend language, the list push_back which requires CopyConstructible is SFINAE'd away, leaving only the overload requiring MoveConstructible. In such a list design, and with the old rules that an lvalue could bind to an rvalue-reference, then the push_back would have implicitly moved from a twice.

Note that we were in no danger at any time of list actually behaving this way. The authors were simply trying to set up a situation where const value_type& and value_type&& were not overloaded, and you had only value_type&& in the overload set.

如果没结果 2024-12-07 16:57:00

您可以通过右值提供它,例如通过函数返回。

unique_ptr<int> make_unique() {
    return unique_ptr<int>(new int);
}
int main() {
    list<unique_ptr<int>> lst;
    lst.push_back(make_unique());
}

此外,您可以显式std::move 到列表中。

You can provide it by rvalue- for example, by function return.

unique_ptr<int> make_unique() {
    return unique_ptr<int>(new int);
}
int main() {
    list<unique_ptr<int>> lst;
    lst.push_back(make_unique());
}

In addition, you can explicitly std::move into the list.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文