繁体   English   中英

C ++,在函数中使用const左值和右值引用

[英]C++, take const lvalue and rvalue reference in a function

我有一些方法需要让他们能够通过const lvalue(将其复制到此处)和rvalue引用(用于速度)来获取变量

struct Object {
    ...
    Object(Object&& o) { ... }
    Object(const Object& o) { ... }
    ...
};

...

struct SomeClass {
    ...
    Object arr[7];

    void copy(int pos,const Object& o) { arr[pos] = o; }
    void copy(int pos,Object&& o) { arr[pos] = o; }
    ...
};

因此,在SomeClass中,两种复制方法是完全相同的。 唯一的区别是,在一个对象中将以const形式进行传递,将被复制,而在另一个对象中则被传递以供快速复制使用以作为右值引用。

这两种方法的代码完全相同。

现在,在上面的示例中并没有那么悲惨,但是,我的方法稍大一些,大约9-15行。 显然,解决方法是像在此一样复制它们,但是感觉不对。

如何重用复制方法的代码?

首先,在两种情况下都要进行副本分配:

void copy(int pos,const Object& o) { arr[pos] = o; }
void copy(int pos,Object&& o) { arr[pos] = o; }

如果有名称,则为左值。 在第二个函数中, o有一个名称,因此它是一个左值(尽管是右值引用)。 您想要arr[pos] = std::move(o);

避免必须写两次copy的通常方法是按值取o并从其移走:

void copy(int pos, Object o) { arr[pos] = std::move(o); }

如果传递一个左值,然后将其赋值到arr[pos] ,则o将被复制构造。 如果传递一个右值,则将构造o ,然后将其进一步分配给数组。 因此,在右值情况下,您仍然避免复制,但在两种情况下都需要多花钱。 如果搬家很便宜,应该没有多少额外的开销。

但是,请注意,这不适用于不支持移动语义的旧式类型。 在这种情况下,此函数将复制您所传递的内容,然后从该副本进行复制分配,而使用引用的两个重载将仅复制一份。

通用引用和std::forward允许您实现完美的转发。 这是修改后的copy

template <typename T>
void copy(int pos, T&& o) {arr[pos] = std::forward<T>(o);}

如果您担心从其他类型到Object隐式转换,则还可以在copy正文中添加static_assert 如果传递一个左值Object进行copy ,则T将被推导为Object& std::forward<Object&>返回引用。 因此,将选择副本分配过载。 如果传递一个r值Object进行copy ,则T将被推导为Object std::forward<Object&>返回Object&& 由于std::forward<Object>(o)也是一个右值,因此将选择移动分配运算符。

暂无
暂无

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

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