r3live ThreadPool (1)右值引用及相关内容

1. 定义:

左值:常规变量;右值:临时变量。
右值引用:右值的引用,符号:&&。
注:右值引用,如果有变量名字,也会看作为左值(这将引出forward的定义)。

all named values (such as function parameters) always evaluate as lvalues (even those declared as rvalue references)

2. 右引用的好处

  • 问题引出:重复的构造-析构
class Class{};
# case 1
a=Class();
# case 2
void fun(Class c){}
fun(Class());
  • 右引用的好处:
    于是定义移动构造函数、移动赋值函数等,减少右引用情况下,不必要的构造-析构过程。
  • std::move():
    如果我们希望某左值也能使用这个好处,且它在之后不会被用到,则可以调用 std::move将左值转换为右值。

template <class T>
typename remove_reference<T>::type&& move (T&& arg) noexcept;

std::move无论传入左值还是右值,都是返回右值。
注:std::move的定义需配合以下说明来理解:

C++11 standard provides special rules for reference collapsing, which are as follows:
Object & & = Object &
Object & && = Object &
Object && & = Object &
Object && && = Object &&

3. 右引用的问题

使用右引用时,一个问题出现了。有名字的量都会被作为左值;所以如果函数某参数的类型为右引用,该值在函数内部仍会作为左值来传递,这将不利于函数内的传值操作(参考 https://www.cplusplus.com/reference/utility/forward/?kw=forward

为了让右引用值在有名字的情况下仍能被作为右值来传递,官方定义了函数std::forward和相关的规则:

template <class T> T&& forward (typename remove_reference<T>::type& arg) noexcept;
template <class T> T&& forward (typename remove_reference<T>::type&& arg) noexcept;

在这巧妙的设计下,右引用或左引用可以被保持:

void overloaded( int const &arg ) { std::cout << "by lvalue\n"; }
void overloaded( int && arg ) { std::cout << "by rvalue\n"; }

template <class T> void fun (T&& x) {
  overloaded (x);                   // always an lvalue
  overloaded (std::forward<T>(x));  // rvalue if argument is rvalue
}

注1:需要注意这里的T!! T与x是左值还是右值无关。
注2:如果无引用的类型传入&&类型,会被视为&类型。


参考测试代码完整版:

#include <utility>      // std::move
#include <iostream>     // std::cout
#include <vector>       // std::vector
#include <string>       // std::string

void overloaded( int const &arg ) { std::cout << "by lvalue\n"; }
void overloaded( int && arg ) { std::cout << "by rvalue\n"; }

template< typename t >void forwarding( t && arg ) {
   // 0. no action
   overloaded( arg );
   // 1. move()
   overloaded( std::move( arg ) ); // conceptually this would invalidate arg
   // 2. forward()
   overloaded( std::forward< t >( arg ) );
}

int main () {
   //=============== move() can avoid copy ==================
   std::string foo = "foo-string";
   std::string bar = "bar-string";
   std::vector<std::string> myvector;
   // 0.no action
   myvector.push_back (foo);                    // copies
   // 1.move()
   myvector.push_back (std::move(bar));         // moves
   std::cout<<bar<<std::endl; // no longer exist
   myvector.push_back (std::move("abc-string"));// no action
   // 2.false usage of forward()
   myvector.emplace_back(std::forward<std::string>(foo));// false !!
   std::cout<<foo<<std::endl;//no longer exist

   std::cout << "myvector contains:";
   for (std::string& x:myvector) std::cout << ' ' << x;
   std::cout << '\n';

   //================= check type of return value ==================
   std::cout << std::endl;
   forwarding( 5 );
   std::cout << std::endl;
   int x = 5;
   forwarding( x );

   return 0;
}

参考链接

官方:https://www.cplusplus.com/reference/utility/forward/?kw=forward
官方:https://www.cplusplus.com/reference/utility/move/
清晰的说明:https://stackoverflow.com/questions/7510182/how-does-stdmove-transfer-values-into-rvalues

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,076评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,658评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,732评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,493评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,591评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,598评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,601评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,348评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,797评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,114评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,278评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,953评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,585评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,202评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,180评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,139评论 2 352

推荐阅读更多精彩内容

  • 右值引用是个效率工具,减少拷贝。C++11标准提出的一类数据类型。用于实现转移语义(move semantic)与...
    book_02阅读 85评论 0 1
  • 本文根据众多互联网博客内容整理后形成,引用内容的版权归原始作者所有,仅限于学习研究使用,不得用于任何商业用途。 左...
    深红的眼眸阅读 11,273评论 1 12
  • 右值引用是cpp11引入的很重要的特性,是为了支持一下两个特性而引入的: 去除不必要的对象内存拷贝,极大提高了程序...
    Jesonwoo阅读 675评论 0 0
  • 在std::promise范例中,使用了std::ref将future对象传递给引用参数类型的任务函数。 std:...
    hijiang阅读 1,032评论 0 0
  • 首先,本章很长,也较难理解,建议读者有大段连续的时间看这个。。。 3.3.1 指针成员与拷贝构造 关于拷贝构造函数...
    zinclee123阅读 680评论 0 0