本文为第五部分,目录请参阅概述部分:http://www.cnblogs.com/harrywong/p/cpp-rvalue-references-explained-introduction.html

右值引用就是右值吗?

同之前一样,给出一个X类,让我们可以重载它的拷贝构造函数和拷贝赋值操作符来实现move语义。现在做如下考虑:

void foo(X&& x)
{
  X anotherX = x;
  // ...
}

一个有趣的问题就是,在foo函数内,哪一个x的拷贝构造函数重载将会被调用。这里,x是一个被声明为右值引用的变量,也就是说,一个在一般情况下或者在更好的情况下(即使并不是必须的)指代一个右值。因此,也许可以期待x本身应该像是一个右值绑定,也就是说:

X(X&& rhs);

应该被调用。换另一种说法,一个人可能会期待任何被声明为右值引用的,其本身也是一个右值。然后右值引用的设计者们采取了更为微妙的一种解决方案:

被声明为右值引用的可能既是左值也可能是右值。这里判断的标准在于:如果它有名字,那么它就是左值。否则就是右值。

就上面的例子,被声明为右值引用的有了一个名字,那么因此它是一个左值:

void foo(X&& x)
{
  X anotherX = x; // 调用 X(X const & rhs)
}

这里就是一个被声明为右值引用并且并没有名字,因此它是一个右值:

X&& goo();
X x = goo(); // 调用 X(X&& rhs) 因为在表达式的右手边
               // 并没有名字

这里有关于这种设计的原理阐述:假设默许move语义发生在一个有名字的东西上面,如下:

X anotherX = x;
// x依然在作用域内!

将是十分危险且混乱的,并且是很容易出错的。因为我们刚刚移动的东西,依然在随后的代码中可以被访问到。但是move语义的整个要点在于它就是应用在那些并不用在意移动后的情况的对象上,严格意义上而言,那些我们从它那里移动后会销毁并且放任不管是没有问题的。因此才有了这个规则:“如果它有个名字,那么它是一个左值。”

这里有一个例子显示了「如果它有一个名字规则」的重要性。假设你已经写了一个叫做Base的类,然后你通过重载Base的拷贝构造函数和赋值操作符来实现move语义。

Base(Base const & rhs); // 非move语义
Base(Base&& rhs); // move语义

现在你写了一个Derived的类,他继承于Base。为了保证move语义被实施在Derived对象的Base部分,你必须也同时重载Derived的拷贝构造函数和赋值操作符。让我们来看一下拷贝构造函数,拷贝赋值操作符的处理是类似的。对应于左值的版本比较简单直接:

Derived(Derived const & rhs)
  : Base(rhs)
{
  // 针对Derived特定的操作
}

对应于右值的版本有一个很大的微妙的不同。下面就是有人没有意识到「如果它有一个名字规则」可能写出来的:

Derived(Derived&& rhs)
  : Base(rhs) // 错误:rhs是一个左值
{
  // 针对Derived特定的操作 f
}

如果我们像那样写代码,那么non-moving的Base拷贝构造函数的版本将会被调用,因为rhs有一个名字,是一个左值。我们想要调用的是Base的moving构造函数,我们需要这样写:

Derived(Derived&& rhs)
  : Base(std::move(rhs)) // 好,调用Base(Base&& rhs)
{
  // 针对Derived特定的操作
}

翻译「C++ Rvalue References Explained」C++右值引用详解 Part5:右值引用就是右值吗?的更多相关文章

  1. 翻译「C++ Rvalue References Explained」C++右值引用详解 Part1:概述

    本文系对「C++ Rvalue References Explained」 该文的翻译,原文作者:Thomas Becker. 该文较详细的解释了C++11右值引用的作用和出现的意义,也同时被Scot ...

  2. 翻译「C++ Rvalue References Explained」C++右值引用详解 Part3:右值引用

    本文为第三部分,目录请参阅概述部分:http://www.cnblogs.com/harrywong/p/4220233.html. 右值引用 如果x是任意类型,那么x&&则被称作一个 ...

  3. 翻译「C++ Rvalue References Explained」C++右值引用详解 Part8:Perfect Forwarding(完美转发):解决方案

    本文为第八部分,目录请参阅概述部分:http://www.cnblogs.com/harrywong/p/cpp-rvalue-references-explained-introduction.ht ...

  4. 翻译「C++ Rvalue References Explained」C++右值引用详解 Part6:Move语义和编译器优化

    本文为第六部分,目录请参阅概述部分:http://www.cnblogs.com/harrywong/p/cpp-rvalue-references-explained-introduction.ht ...

  5. 翻译「C++ Rvalue References Explained」C++右值引用详解 Part4:强制Move语义

    本文为第四部分,目录请参阅概述部分:http://www.cnblogs.com/harrywong/p/4220233.html. 强制Move语义 众所周知,正如C++标准的第一修正案所陈述:“委 ...

  6. 「翻译」Unity中的AssetBundle详解(二)

    为AssetBundles准备资源 使用AssetBundles时,您可以随意将任何Asset分配给所需的任何Bundle.但是,在设置Bundles时,需要考虑一些策略.这些分组策略可以使用到任何你 ...

  7. 「翻译」Unity中的AssetBundle详解(一)

    AssetBundles AssetBundle是一个存档文件,其中包含平台在运行时加载的特定资产(模型,纹理,预制,音频剪辑,甚至整个场景).AssetBundles可以表示彼此之间的依赖关系;例如 ...

  8. Linux 小知识翻译 - 「协议(protocol)」

    对于理解服务器和网络来说,「协议」是不可缺少的概念. 「协议(protocol)」有「规则,规定」的意思. 实际上「协议」的函数很广,在通信领域,「协议」规定了「在通信时,什么样的情况下,以什么样的顺 ...

  9. Linux 小知识翻译 - 「内核(kernel)」

    上次介绍了Linus Torvalds, 这次介绍他开发的「内核」. 经常听人提到「Linux kernel」,但如果被问到「kernel究竟是什么?」的话,会出乎意料的觉得难以回答. 那么,kern ...

随机推荐

  1. 利用JavaScript来实现用动态检验密码强度

    平时我们会在某些网站的注册页面或者更改密码的页面发现当我们输入密码时,会有一个类似于进度条的长条进行提示用户输入的密码强度.如下图: 我看到有些人用几张不同的图片来替换,这样似乎可以,但是不太好.所以 ...

  2. C 语言学习guideline

    Kernighan和Ritchie的<The C Programming Language>(中译名<C程序设计语言>)堪称经典中的经典,不过旧版的很多内容都已过时,和现在的标 ...

  3. 贴一个CMemDC 代码,这东西真不错噢,短小精悍,可谓极品

    罗索客 发布于 2006-11-28 21:53 点击:3941次  来自: 原文: http://yuantao82.spaces.live.com/Blog/cns!8FC0A772D812A22 ...

  4. JQuery.Ajax + 跨域 (crossDomain) + POST + JSON + WCF RESTful, 5大陷阱和解决方案

    JQuery.Ajax + 跨域 (crossDomain) + POST + JSON + WCF RESTful, 5大陷阱和解决方案 最近在开发WSS RESTful服务的时候, 碰到了这些个纠 ...

  5. 交叉编译 tesseract

      官方参考资料说明: tesseract 依赖库: (https://github.com/tesseract-ocr/tesseract/wiki/Compiling#linux) leptoni ...

  6. spring项目中service方法开启线程处理业务的事务问题

    1.前段时间在维护项目的时候碰到一个问题,具体业务就是更新已有角色的资源,数据库已更新,但是权限控制不起效果,还是保留原来的权限. 2.排查发现原有的代码在一个service方法里有进行资源权限表的更 ...

  7. JSON序列化类

    '''pyhton的dict对象可以直接序列化为JSON的{},不过很多时候 我们更喜欢用class表示对象,比如定义Student类,然后序列化''' import json class Stude ...

  8. 读书笔记---HTML5实战 MARCO CASARIO(前六章)

    1:行内元素转化为块级元素①display②position③float; 2:语义化; 3:微数据itemscope/itemprop/itemtype; 4:新表单元素,form外的表单元素可以用 ...

  9. Django-GET和POST小记

    import requests requests.get(url='xxx') # 本质上就是: requests.request(method='get',url='xxx') import jso ...

  10. Spring+thymeleaf

    1.导入jar包 2.配置 3.标签使用 th:text th:utext th:object th:if th:switch th:case th:each="person:userlis ...