按值或右值引用接受仅移动参数 [英] Accept move-only parameter by value or rvalue reference

查看:76
本文介绍了按值或右值引用接受仅移动参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此帖子的可接受答案按值传递与按右​​值传递reference 表示:

The accepted answer of this post Pass by value vs pass by rvalue reference says that:


仅移动类型(如 std :: unique_ptr ),按值传递似乎是常态...

For move-only types (as std::unique_ptr), pass-by-value seems to be the norm...

我有点怀疑那。假设有一些不可复制的类型, Foo ,移动起来也不便宜;以及某些类型为 Bar 且成员为 Foo 的计算机。

I'm a little bit doubtful about that. Let's say there is some non-copyable type, Foo, which is also not cheap to move; and some type Bar that has a member Foo.

class Foo {
public:
    Foo(const Foo&) = delete;
    Foo(Foo&&) { /* quite some work */ }
    ...
};

class Bar {
public:
    Bar(Foo f) : f_(std::move(f)) {}    // (1)
    Bar(Foo&& f) : f_(std::move(f)) {}  // (2)
    // Assuming only one of (1) and (2) exists at a time

private:
    Foo f_;
};

然后输入以下代码:

Foo f;
...
Bar bar(std::move(f));

构造函数(1)产生2次移动构造,而构造函数(2)仅产生1次移动。我也记得在斯科特·迈耶斯(Scott Meyers)的 Effective Modern C ++ 中读到了有关此内容的信息,但记不起来是什么。

Constructor (1) incurs 2 move constructions, while constructor (2) only incurs 1. I also remember reading in Scott Meyers's Effective Modern C++ about this but can't remember which item immediately.

所以我的问题是,仅移动类型(或更笼统地说,当我们要转移参数的所有权时),我们不应该更喜欢通过右值引用来获得更好的性能吗?

So my question is, for move-only types (or more generally, when we want to transfer the ownership of the argument), shouldn't we prefer pass-by-rvalue-reference for better performance?

UPDATE:我知道按值传递构造函数/赋值运算符(有时称为 unifying ctors / assignment operator)可以帮助消除重复的代码。我应该对以下情况更感兴趣:(1)性能很重要,(2)类型不可复制,因此没有重复的ctor / assigning运算符接受 const 左值引用参数。

UPDATE: I'm aware that the pass-by-value constructors/assignment operators (sometimes called unifying ctors/assignment operators) can help eliminate duplicate code. I should say I'm more interested in the case when (1) performance is important, and (2) the type is non-copyable and so there are no duplicate ctors/assignment operators which accept const lvalue reference arguments.

更新2:因此,我发现了Scott Meyers的博客中有关特定问题的信息: http://scottmeyers.blogspot.com/2014 /07/should-move-only-types-ever-passed.html 。该博客讨论了他在 Effective Modern C ++ 的第41项中主张的原因:

UPDATE 2: So I've found Scott Meyers's blog about the specific problem: http://scottmeyers.blogspot.com/2014/07/should-move-only-types-ever-be-passed.html. This blog discusses the reason that he advocates in Item 41 of his Effective Modern C++ that:


考虑通过可复制参数 ...的值,这些参数最便宜的移动 ... [和] 始终复制

Consider pass by value only for copyable parameters...that are cheap to move...[and] always copied.

该项目中有一个关于按值传递与右值引用的广泛讨论,在此不再赘述。关键是,这两种方式都有其优点和缺点,但是对于转移仅移动对象的所有权,通过rvalue引用传递似乎是更可取的。

There is an extensive discussion in that item about pass by value vs. rvalue reference, too much to be quoted here. The point is, both ways have their own advantages and disadvantages, but for transferring the ownership of a move-only object, pass by rvalue reference seems to be preferable.

推荐答案

在这种情况下,我们可以吃蛋糕。仅针对类似Foo的引用启用的模板构造函数可为我们提供完美的转发功能以及构造函数的单个实现:

In this case we can have our cake and eat it. A template constructor enabled only for Foo-like references gives us perfect forwarding plus a single implementation of a constructor:

#include <iostream>
#include <utility>

class Foo {
public:
    Foo() {}
    Foo(const Foo&) = delete;
    Foo(Foo&&) { /* quite some work */ }
};

class Bar {
public:
  template<class T, std::enable_if_t<std::is_same<std::decay_t<T>, Foo>::value>* = nullptr>
    Bar(T&& f) : f_(std::forward<T>(f)) {}  // (2)
    // Assuming only one of (1) and (2) exists at a time

private:
    Foo f_;
};

int main()
{
  Foo f;
  Bar bar(std::move(f));

  // this won't compile
//  Foo f2;
//  Bar bar2(f2);

}

这篇关于按值或右值引用接受仅移动参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆