3 回答
TA贡献1796条经验 获得超10个赞
C+03引用(在C+11中现在称为lvalue引用)的最大区别是,它可以像临时的那样绑定到rvalue,而不必是Const。因此,这个语法现在是合法的:
T&& r = T();
rvalue参考主要提供以下内容:
移动语义..现在可以定义一个移动构造函数和移动赋值操作符,它接受一个rvalue引用,而不是通常的const-lvalue引用。迁移功能类似于副本,只是它没有义务保持源不变;实际上,它通常修改源,使其不再拥有移动的资源。这对于消除无关的副本是很好的,特别是在标准库实现中。
例如,复制构造函数可能如下所示:
foo(foo const& other){ this->length = other.length; this->ptr = new int[other.length]; copy(other.ptr, other.ptr + other.length, this->ptr);}
如果这个构造函数是临时的,那么这个副本就没有必要了,因为我们知道这个临时构造函数只会被销毁,为什么不利用临时分配的资源呢?在C+03中,无法阻止复制,因为我们无法确定我们是临时传递的。在C+11中,我们可以重载一个移动构造函数:
foo(foo&& other){ this->length = other.length; this->ptr = other.ptr; other.length = 0; other.ptr = nullptr;}
注意这里最大的区别:Move构造函数实际上修改了它的参数。这将有效地“移动”临时对象到正在构造的对象中,从而消除不必要的副本。
属性显式转换为rvalue引用的临时和非Const值引用将使用移动构造函数。std::move
函数(它只执行转换)。下面的代码都调用移动构造函数f1
和f2
:
foo f1((foo())); // Move a temporary into f1; temporary becomes "empty"foo f2 = std::move(f1); // Move f1 into f2; f1 is now "empty"
完美转发..rvalue引用允许我们正确地转发模板函数的参数。例如,这个工厂功能:
template <typename T, typename A1>std::unique_ptr<T> factory(A1& a1){ return std::unique_ptr<T>(new T(a1));}
如果我们打电话factory<foo>(5)
,这个论点将被推断为int&
,它不会绑定到文字5,即使foo
构造函数采用int
..好吧,我们可以用A1 const&
,但如果foo
接受非Const引用的构造函数参数?要建立一个真正通用的工厂功能,我们必须在A1&
继续A1 const&
..如果工厂采用一个参数类型,那么这可能很好,但是每一个附加的参数类型都会将所需的重载设置为2,这很快就无法维护了。
rvalue引用通过允许标准库定义std::forward
函数,可以正确转发lvalue/rvalue引用。
这使我们能够像这样定义工厂函数:
template <typename T, typename A1>std::unique_ptr<T> factory(A1&& a1){ return std::unique_ptr<T>(new T(std::forward<A1>(a1)));}
现在,参数的rvalue/lvalue-ness在传递给T
的构造函数,这意味着如果使用rvalue调用工厂,T
用rvalue调用工厂的构造函数。如果使用lvalue调用工厂,T
它的构造函数是用lvalue调用的。改进后的工厂函数可以工作,因为有一个特殊的规则:
函数参数类型为
T&&
哪里T
是模板参数,函数参数是类型的lvalue。A
,类型A&
用于模板参数推导。
因此,我们可以像这样使用工厂:
auto p1 = factory<foo>(foo()); // calls foo(foo&&)auto p2 = factory<foo>(*p1); // calls foo(foo const&)
重要参考属性:
- 为了解决过载问题,
lvalue更喜欢绑定于lvalue引用,rvalue更喜欢绑定而不是rvalue引用。
..因此,临时人员为什么更喜欢调用移动构造函数/移动赋值操作符,而不是复制构造函数/赋值运算符。 rvalue引用将隐式绑定到rvalue和作为隐式转换结果的临时变量。
..E.
格式良好,因为Float是隐式可转换为int的;引用将是临时的,这是转换的结果。float f = 0f; int&& i = f;
命名的rvalue引用是lvalue。未命名的rvalue引用是rvalue。
这一点很重要,请理解为什么
打电话是必要的,因为:std::move
foo&& r = foo(); foo f = std::move(r);
TA贡献1802条经验 获得超5个赞
指.的术语T&&
与类型扣除一起使用时(如用于完美转发)被通俗地称为转发参考..“普遍参考”一词是由ScottMeyers发明的
这是因为它可以是r值,也可以是l值。
例如:
// templatetemplate<class T> foo(T&& t) { ... }// autoauto&& t = ...;// typedeftypedef ... T;T&& t = ...;// decltypedecltype(...)&& t = ...;
- 3 回答
- 0 关注
- 762 浏览
添加回答
举报