C++ Primer 笔记——理解std::move

标准库move函数是使用右值引用的模板的一个很好的例子。标准库是这样定义std::move的:

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

我们考虑如下代码的工作过程:

std::string s1("hi"), s2;
s2 = std::move(string("hi"));    // 正确,从一个右值移动数据
s2 = std::move(s1);                // 正确,但是在赋值之后,s1的值是不确定的

在第一个赋值中,实参是string类型的右值,因此过程为:

  • 推断T的类型为 string
  • remove_reference<string> 的 type 成员是 string
  • move 返回类型是 string&&
  • move 的函数参数t的类型为 string&&

因此,这个调用实例化 move<string>,即函数

string&& move(string &&t)

在第二个赋值中,实参是一个左值,因此:

  • 推断T的类型为 string&
  • remove_reference<string&> 的 type 成员是 string
  • move 返回类型是 string&&
  • move 的函数参数t的类型为 string& &&,会折叠成 string&

因此,这个调用实例化 move<string&>,即

string&& move(string &t)

  通常情况下,static_cast 只能用于其他合法的类型转换。但是有一条针对右值的特许规则:虽然不能隐式的将一个左值转换成右值引用,但我们可以用static_cast显示的将一个左值转换为一个右值。

时间: 2024-10-24 21:27:46

C++ Primer 笔记——理解std::move的相关文章

C++11学习笔记:std::move和std::forward源码分析

std::move和std::forward是C++0x中新增的标准库函数,分别用于实现移动语义和完美转发. 下面让我们分析一下这两个函数在gcc4.6中的具体实现. 预备知识 引用折叠规则: X& + & => X& X&& + & => X& X& + && => X& X&& + && => X&& 函数模板参数推导规则(右值引用参数部分):

C++ Primer笔记8_动态内存_智能指针

1.动态内存 C++中,动态内存管理是通过一对运算符完成的:new和delete.C语言中通过malloc与free函数来实现先动态内存的分配与释放.C++中new与delete的实现其实会调用malloc与free. new分配: 分配变量空间: int *a = new int; // 不初始化 int *b = new int(10); //初始化为10 string *str = new string(10, ); 分配数组空间: int *arr = new int[10];//分配的

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

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

C++ Primer笔记2_四种类型转换_异常机制

1.类型转换 命名的强制类型转换: 有static_cast.dynamic_cast.const_cast.reinterpret_cast static_cast: 编译器隐式执行的任何类型转换都可以由static_cast完成 当一个较大的算术类型赋值给较小的类型时,可以用static_cast进行强制转换. 可以将void*指针转换为某一类型的指针 可以将基类指针强制转换为派生类指针,但是不安全. 无法将const转化为nonconst,这个只有const_cast才可以办得到 举例:

重读C++ Primer笔记

C++ Primer 5E 有符号和无符号 无符号类型和有符号类型混合运算时,有符号数会被提升至无符号类型,如果其值为负责会产生错误. int main() { unsigned int u = 10; int i = -42; std::cout<<u+i<< std::endl; // 4294967264 if sizeof(int)==4 return 0; } 列表初始化 列表初始化过程不允许损失数据类型精度,所以下面代码中的两行无法通过编译 int main() { d

C++ Primer笔记6_STL之泛型算法

1.泛型算法: 大多数算法定义在头文件algorithm中,标准库还在头文件numeric中定义了一组数值泛型算法 只读算法: 举例: find函数用于找出容器中一个特定的值,有三个参数 int val = 10;//val为我们需要查找的值 auto result = find(vec.begin(), vec.end(), val): cout << "The value "<< val << (result == vec.end() ? &qu

C++ Primer笔记13_运算符重载_总结

总结: 1.不能重载的运算符: . 和 .* 和 ?: 和 ::  和 sizeof 和 typeid 2.重载运算符有两种基本选择: 类的成员函数或者友元函数, 建议规则如下: 运算符 建议使用 所有一元运算符 成员函数 = () [] -> 必须是成员函数 += -= /= *= ^= &= != %= >>= <<= , 似乎带等号的都在这里了. 成员函数 所有其它二元运算符, 例如: –,+,*,/ 友元函数 3.前几篇中的实例,现在汇总Person类的程序:

C++ Primer笔记4_类的静态成员_IO库

1.类的静态成员 static成员变量与函数 static成员变量:必须在类外初始化:(const或引用类型变量必须在构造函数初始化列表里初始化) static成员函数: 不依赖于类,相当于类里的全局函数(可以由该类对象调用,也可以 类名::函数名()的形式调用) 不包含this指针,不能声明为const,声明为const表示不会改变对象,而static成员函数存在于任何对象之外. 相当于把访问范围限制在所在的类中!  注意:不能访问类中非static成员变量以及非static成员函数. 注意:

C++ Primer笔记3_默认实参_类初探_名字查找与类的作用域

1.默认函数实参 在C++中,可以为参数指定默认值,C语言是不支持默认参数的,Java也不支持! 默认参数的语法与使用: (1)在函数声明或定义时,直接对参数赋值.这就是默认参数: (2)在函数调用时,省略部分或全部参数.这时可以用默认参数来代替. 注意事项: (1)函数默认值只能赋值一次,或者是在声明中,或者是在定义中,都可以. (2)默认参数定义的顺序为自右到左.即如果一个参数设定了缺省值时,其右边的参数都要有缺省值.比如int f(int a, int b=1,int c=2,int d=