c语言中%11s是什么意思,T&& (双和符号)是什么意思在C 11?

本文深入探讨了C++中的右值引用,包括其如何启用移动语义,减少不必要的拷贝,提高效率。通过移动构造函数和移动赋值运算符,可以更有效地处理临时对象。此外,右值引用还解决了模板函数中完美转发的问题,使得参数的左值/右值特性在转发时得以保留。工厂函数示例展示了如何利用右值引用实现通用性。总结了右值引用的重要特性,如l值与r值的绑定规则,以及如何通过std::move触发移动操作。
摘要由CSDN通过智能技术生成

这里是rvalue references的介绍。

这里有一个奇妙的深入了解微软的标准库developers之一的值引用。(但阅读本文之前,请参阅本回答之后的注释中的Caution)。

C 03引用(现在在C 0x中称为左值引用)的最大区别是它可以像临时的那样绑定到右值,而不必是const。因此,这种语法现在是合法的:

T&& r = T();

右值引用主要提供以下内容:

移动语义。现在可以定义一个移动构造函数和移动赋值运算符,它使用一个右值引用而不是通常的常量值引用。一个移动的功能像一个副本,除了它没有义务保持源不变;实际上,它通常修改源,使其不再拥有移动的资源。这是伟大的消除无关的副本,特别是在标准库实现。

例如,复制构造函数可能如下所示:

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 0x中,我们可以重载一个移动构造函数:

foo(foo&& other)

{

this->length = other.length;

this->ptr = other.ptr;

other.length = 0;

other.ptr = nullptr;

}

注意这里的巨大差异:move constructor实际上修改它的参数。这将有效地将临时“移动”到正在构造的对象中,从而消除不必要的副本。

move构造函数将用于临时和非const常量引用,它们使用std :: move函数(仅执行转换)显式转换为右值引用。以下代码都调用f1和f2的move构造函数:

foo f1((foo())); // Move a temporary into f1; temporary becomes "empty"

foo f2 = std::move(f1); // Move f1 into f2; f1 is now "empty"

完美的转发。右值引用允许我们正确地转发模板函数的参数。以这个工厂函数为例:

template

std::unique_ptr factory(A1& a1)

{

return std::unique_ptr(new T(a1));

}

如果我们调用factory(5),则参数将被推导为int& amp,这将不会绑定到文字5,即使foo的构造函数接受int。好吧,我们可以改用A1 const&,但如果foo接受构造函数参数的非const引用?为了使一个真正的通用工厂功能,我们将不得不超载工厂在A1&和A1 const&如果工厂需要1个参数类型,那么这可能很好,但是每个附加的参数类型都会将必要的重载设置乘以2.这是非常快速的不可维护的。

右值引用通过允许标准库定义一个可以正确转发lvalue / rvalue引用的std :: forward函数来解决这个问题。有关std :: forward的工作原理的更多信息,请参阅this excellent answer。

这使我们可以这样定义工厂函数:

template

std::unique_ptr factory(A1&& a1)

{

return std::unique_ptr(new T(std::forward(a1)));

}

现在,当传递给T的构造函数时,参数的rvalue / lvalue-ness被保留。这意味着如果工厂用一个右值调用,T的构造函数被调用一个右值。如果工厂以左值调用,则T的构造函数使用左值调用。改进的工厂功能的工作原理是一个特殊的规则:

When the function parameter type is of

the form T&& where T is a template

parameter, and the function argument

is an lvalue of type A, the type A& is

used for template argument deduction.

因此,我们可以使用工厂这样:

auto p1 = factory(foo()); // calls foo(foo&&)

auto p2 = factory(*p1); // calls foo(foo const&)

重要的右值引用属性:

>对于重载解析,l值偏好绑定到lvalue引用,rvalues偏好绑定到rvalue引用。因此,为什么临时优选在复制构造函数/赋值运算符上调用移动构造函数/移动赋值运算符。 >右值引用将隐式绑定到右值和作为隐式转换结果的临时值。即float f = 0f;内部&& i = f;是良好形成的,因为float是隐式可转换为int;引用将是转换的结果的临时。 >命名的右值引用是左值。未命名的右值引用是右值。这是很重要的理解为什么std :: move调用是必要的:foo&& r = foo(); foo f = std :: move(r);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值