C++ 右值引用与移动操作

右值引用和移动操作是C++11提出的新概念,通过这些操作,可以降低拷贝操作带来的消耗。先来简单介绍一下左值和右值。

左值一般指的是一个对象,或者说是一个持久的值,例如赋值的返回值、下标操作、解引用以及前置递增等。

右值是一个短暂的值,比如一个表达式的求值结果、函数返回值以及一个字面值等。

为了区分,把一般的引用称为左值引用,必须绑定到右值的引用称为右值引用,以&&表示。右值引用有这两个特性:

右值引用只能绑定到临时对象,所引用的对象将要被销毁,并且没有其他用户

这也意味着,我们可以自由地接管引用对象的资源。

通常一个变量可以认为是左值,也即是一个对象。那么如何获得右值呢?可以显示转换为对应的右值引用,也可以调用标准库函数std::move()。

move()承诺了我们不再使用移后源,不保证移后源的状态和值。

实际上,移动操作窃取了对象资源的控制权,从而避免了不必要的拷贝。

int i = 1;
int&& rr = std::move(i);

移后源对象必须是可以析构的,并且要保证对象依然有效,可以被赋予新值,但是不保证移后源对象中留下的值。

事实上,单纯调用std::move()并不会对对象进行改变,只有另外一个对象接管了资源后,移动才真正完成。

<<C++ primer>>在模板操作中详细解释了std::move的具体实现和工作。

template<typename T> typename remove_reference<T>::type&& move(T&& t)
{
    return static_cast<typename remove_reference<T>::type&&> (t);
}

move的参数是一个T&&,而任何有名字的参数实际上都是左值。也就是说,这个参数可以和任何类型的参数匹配,可以传左值也可以传右值。

时间: 2024-10-25 01:26:02

C++ 右值引用与移动操作的相关文章

C++11的右值引用

右值引用是C++11         引入的新特性.它解决了两类问题:实现移动语义和完美转发.本文大绝大部分内容,来自于文章:http://kuring.me/post/cpp11_right_reference/ 一:左值(lvalue)和右值(rvalue) 最初,在C中,左值和右值的定义如下:左值,是一个可以出现在赋值操作符左边或者右边的表达式:而右值是只能出现在赋值操作符右边的表达式.比如: int a = 42; int b = 43; // a and b are both l-va

【原创】深入理解c++的右值引用

0 左值和右值 一个左值表达式代表的是对象本身,而右值表达式代表的是对象的值:变量也是左值. 1 右值引用作用 为了支持移动操作(包括移动构造函数和移动赋值函数),C++才引入了一种新的引用类型——右值引用,可以自由接管右值引用的对象内容. 2 右值引用绑定的对象 返回非引用类型的函数,产生右值的表达式(算术表达式.关系表达式.位.后置递增递减) 3 和左值引用的区别 绑定的对象(引用的对象)不同,左值引用绑定的是返回左值引用的函数.赋值.下标.解引用.前置递增递减 左值持久,右值短暂,右值只能

Effective Modern C++:05右值引用、移动语义和完美转发

移动语义使得编译器得以使用成本较低的移动操作,来代替成本较高的复制操作:完美转发使得人们可以撰写接收任意实参的函数模板,并将其转发到目标函数,目标函数会接收到与转发函数所接收到的完全相同的实参.右值引用是将这两个不相关的语言特性连接起来的底层语言机制,正是它使得移动语义和完美转发成了可能. 23:理解std::move和std::forward std::move并不进行任何移动,std::forward也不进行任何转发.这两者在运行期都无所作为,它们不会生成任何可执行代码.实际上,std::m

C11右值引用

 int *a = &1; //1为右值 不可取址  const int &&aa = 1;// 右值引用,    //注意  考虑到安全因素,具名变量即使被声明为右值类型也不会被当作右值 而要用std::move函数

C++11之右值引用(二):右值引用与移动语义

上节我们提出了右值引用,可以用来区分右值,那么这有什么用处?   问题来源   我们先看一个C++中被人诟病已久的问题: 我把某文件的内容读取到vector中,用函数如何封装? 大部分人的做法是: void readFile(const string &filename, vector<string> &words) { words.clear(); //read XXXXX } 这种做法完全可行,但是代码风格谈不上美观,我们尝试着这样编写: vector<string&

【转载】C++ 11中的右值引用

本篇随笔为转载,原博地址如下:http://www.cnblogs.com/TianFang/archive/2013/01/26/2878356.html 右值引用的功能 首先,我并不介绍什么是右值引用,而是以一个例子里来介绍一下右值引用的功能: #include <iostream>    #include <vector>    using namespace std; class obj    {    public :        obj() { cout <&l

Item 24: 区分右值引用和universal引用

本文翻译自<effective modern C++>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 古人曾说事情的真相会让你觉得很自在,但是在适当的情况下,一个良好的谎言同样能解放你.这个Item就是这样一个谎言.但是,因为我们在和软件打交道,所以让我们避开"谎言"这个词,换句话来说:本Item是由"抽象"组成的. 为了声明一个指向T类型的右值引用,你会写T&&.因此我们可以"合理"地假设:如果你在源代

c++11之右值引用和std::move

这两个特性是c++11里比较有性能提升意义的.个人认为这两个特性也体现了c++对性能提升的极限追求. 通过改写经典c++面试题mystring来体会 move不能减少临时变量的产生,但是可以减少内存的维护量 代码 //右值引用 /* 左值对象:持久存在的对象,具有名字,可以对其去地址 右值对象:临时对象,表达式结束后它就没了,不能对它取地址,它也没有名字~ 右值引用类型:引用右值的类型,用&&来表示 */ /*****************************************

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

本文为第三部分,目录请参阅概述部分:http://www.cnblogs.com/harrywong/p/4220233.html. 右值引用 如果x是任意类型,那么x&&则被称作一个对x的右值引用(rvalue reference).为了更好区分,原来的引用x&现在也被称作左值引用(lvalue reference). 一个右值引用是一种同原始引用x&的行为非常类似的类型,但是有一些特例.最重要的一个就是当面临方法重载决议的时候,左值倾向于旧式的左值引用,而右值偏向于新的