c++ 移动语义并完善转发差异

我已经从这个问题得到了什么样的移动语义:
What are move semantics?

但是我仍然没有得到与移动语义相关的完美转发.

有人能用简单的英语和一个简单的例子解释完美的转发意味着什么?

最佳答案
简单的英语尝试

这个问题可能太复杂了,无法通过简单的英语句子准确描述,但是人们可以将完美转发视为将传递给函数的临时值移动到另一个函数的一种方式,就好像第一个函数根本不存在一样,所以没有任何不必要的副本或作业. C 11允许您通过在尝试获取引用(r值或l值)时在r值(&&)和l值(&)引用之间引入一些转换规则来实现此目的他们出来了.

R值引用是C 11的一个特性,它们旨在解决移动语义和完美转发问题

这是简单的英语解释,但如果你想彻底了解这个问题,我建议你阅读以下内容:

问题:

我们希望传递给函数F的一些临时值传递给另一个E而不进行任何复制或赋值.

试图解决这个问题

>如果您尝试通过引用传递它,如

template<typename T> void F(T& a) { E(a); }

你将无法使用临时(他们不是l值)

F(1, 2, 3); // Won't work

>将引用声明为const会延长堆栈上临时值的生命周期(这在历史上是为了避免常见的悬空引用错误),因此以下工作原理

template<typename T> void E(const T& a) {}

template<typename T> void F(const T& a) {
    E(a);
}

但缺点是您必须修改功能的签名以符合此解决方案
>如果我们对E的签名感兴趣(它应该符合某些东西)而不是F的签名,我们可能会侥幸逃脱

template<typename T> void E(T& a) {}

template<typename T> void F(const T& a) {
    E(const_cast<T&>(a));
}

但是如果用真实的const调用它并且得到非常量的,那将触发未定义的行为
>一个无法维护的解决方案可能是定义您需要的所有变体

template<typename T> void E(T& a) {}

template<typename T> void F(T& a) { E(a); }
template<typename T> void F(const T& a) { E(const_cast<T&>(a)); }

但随着参数数量的增加,组合的数量也会增加:这很可能变得不可维护

C 11中的解决方案

C 11定义了一些陈述的规则

“[given] a type TR that is a reference to a type T, an attempt to
create the type “lvalue reference to cv TR” creates the type “lvalue
reference to T”, while an attempt to create the type “rvalue reference
to cv TR” creates the type TR.”

在人形中(TR =对类型T的引用,R =引用):

TR      R
T& & -> T&    // an lvalue reference to cv TR (becomes)-> lvalue reference to T 
T& && -> T&   // an rvalue reference to cv TR (becomes)-> TR (lvalue reference to T) 
T&& & -> T&   // an lvalue reference to cv TR (becomes)-> lvalue reference to T 
T&& && -> T&& // an rvalue reference to cv TR (becomes)-> TR (rvalue reference to T)

这里重要的一点是,现在您可以跟踪函数的类型:您可以接收一个l值并将相同的l值传递给E,或者您可以接收一个r值并传递相同的r值(在转换之后,因为对任何类型引用的l值引用变为l值引用)到E:

template<typename T> void E(T&& a) {}

template<typename T> void F(T&& a) { E(static_cast<T&&>(a)); }

一种同义糖

static_cast<T&&>(a)

std::forward<T>(a); // is the same as static_cast<T&&>(a);

因此,解决问题并使您的生活更轻松的最终代码是

template<typename T> void E(T&& a) {}

template<typename T> void F(T&& a) { E(std::forward<T>(a)); }

Live example

参考文献:Herb Sutter的博客和一些其他来源,遗憾的是我再也找不到了.如果有人对这些有任何疑问,请在下面的评论中写下来,我会更新帖子.谢谢.

转载注明原文:c++ 移动语义并完善转发差异 - 代码日志