C++11之右值引用、move语义

  C++11中增加了一个新的类型,即右值引用(R-value reference),标记为T&& 。而它的目的就是去消除不必要的深拷贝,提高性能。

  概念性的东西就不多说了。直接用代码体现其优势。

  实现一个MyString类:

 1 class MyString {
 2 public:
 3     MyString():m_data(nullptr), m_len(0) {}
 4     MyString(const char* p) {
 5         m_len = strlen(p);
 6         copy_data(p);
 7         std::cout << " Construction Called" << std::endl;
 8     }
 9     MyString(const MyString& lhs) {
10         m_len = lhs.m_len;
11         copy_data(lhs.m_data);
12         std::cout << "Copy Construction Called" << std::endl;
13     }
14     MyString(MyString&& rhs) {
15         m_data = rhs.m_data;
16         m_len = rhs.m_len;
17         rhs.m_data = nullptr;
18         rhs.m_len = 0;
19         std::cout << "Move Construction Called" << std::endl;
20     }
21     MyString& operator=(const MyString&);
22     MyString& operator=(MyString&&);
23     void Print();
24 private:
25     void copy_data(const char* s) {
26         m_data = new char[m_len + 1];
27         strncpy(m_data, s, m_len);
28         m_data[m_len] = 0;
29     }
30 private:
31     char* m_data;
32     size_t m_len;
33 };
34
35 MyString& MyString::operator=(const MyString& lhs) {
36     if (this != &lhs) {
37         m_len = lhs.m_len;
38         copy_data(lhs.m_data);
39     }
40
41     std::cout << "Copy Assignment Called" << std::endl;
42     return *this;
43 }
44
45 MyString& MyString::operator=(MyString&& rhs) {
46     if (this != &rhs) {
47         m_len = rhs.m_len;
48         m_data = rhs.m_data;
49         rhs.m_data = nullptr;
50         rhs.m_len = 0;
51     }
52     std::cout << "Move Assignment Called" << std::endl;
53     return *this;
54 }
55 void MyString::Print() {
56     std::cout << "value:" << m_data << std::endl;
57 }

  move语义是用来将左值转换为右值,这样的目的只是改变了对象的控制权而并没有内存拷贝,从而提高效率。

1 std::vector<std::string> v1;
2 std::vector<std::string> v2 = std::move(v1);

  std::forward 方法用于函数转发,它能按照参数原来的类型转发到另一个函数。STL中的所有容器都实现了基于移动语义的方法 emplace, emplace_front, emplace_back, emplace_after等,如:

int main(int argc, char** argv) {
    std::vector<int> v = {1, 2, 3, 4};
    v.emplace_back(5);
    v.emplace(v.begin(), 0);
    for_each(v.begin(), v.end(), [](int value) {
        std::cout << value << endl;
    });
    system("pause");
    return 0;
}
时间: 2024-12-26 20:35:52

C++11之右值引用、move语义的相关文章

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

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

[转载]如何在C++03中模拟C++11的右值引用std::move特性

本文摘自: http://adamcavendish.is-programmer.com/posts/38190.htm 引言 众所周知,C++11 的新特性中有一个非常重要的特性,那就是 rvalue reference,右值引用. 引入它的一个非常重要的原因是因为在 C++ 中,常常右值,通俗地讲"在等号右边的"临时变量或者临时对象,我们是无法得到它的修改权限的. 由于类的构造和析构机制,往往产生的临时变量或临时对象的拷贝构造及析构,会带来不少的时间.资源消耗. 也同样由于这样的限

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

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

c++11的右值引用、移动语义

对于c++11来说移动语义是一个重要的概念,一直以来我对这个概念都似懂非懂.最近翻翻资料感觉突然开窍,因此记下.其实搞懂之后就会发现这个概念很简单,并无什么高深的地方. 先说说右值引用.右值一般指的是表示式中的临时变量,在c++中临时变量在表达式结束后就被销毁了,之后程序就无法再引用这个变量了.但是c++11提供了一个方法,让我们可以引用这个临时变量.这个方法就是所谓的右值引用. 那么右值引用有什么用呢?避免内存copy! 不同于其它语言,在c++里变量是值语义(在JAVA.Python变量是引

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

右值引用,转移语义与完美转发

1. 左值与右值: C++对于左值和右值没有标准定义,但是有一个被广泛认同的说法:可以取地址的,有名字的,非临时的就是左值;不能取地址的,没有名字的,临时的就是右值. 可见立即数,函数返回的值等都是右值;而对象(包括变量),函数返回的引用,const对象等都是左值. 从本质上理解,创建和销毁由编译器幕后控制的,程序员只能确保在本行代码有效的,就是右值(包括立即数);而用户创建的,通过作用域规则可知其生存期的,就是左值(包括函数返回的局部变量的引用以及const对象),例如: int& foo()

C++11之右值引用:从左值右值到右值引用

C++98中规定了左值和右值的概念,但是一般程序员不需要理解的过于深入,因为对于C++98,左值和右值的划分一般用处不大,但是到了C++11,它的重要性开始显现出来. C++98标准明确规定: 左值是可以取得内存地址的变量. 非左值即为右值. 从这里可以看出,可以执行&取地址的就是左值,其他的就是右值. 这里需要明确一点,能否被赋值不是区分C++左值和右值的区别. 我们给出四个表达式: string one("one"); const string two("two&

C++11之右值引用(三):使用C++11编写string类以及&ldquo;异常安全&rdquo;的=运算符

前面两节,说明了右值引用和它的作用.下面通过一个string类的编写,来说明右值引用的使用. 相对于C++98,主要是多了移动构造函数和移动赋值运算符. 先给出一个简要的声明: class String { public: String(); String(const char *s); //转化语义 String(const String &s); String(String &&s); ~String(); String &operator=(const String

深入右值引用,move语义和完美转发

深入右值引用,move语义和完美转发 转载请注明:http://blog.csdn.net/booirror/article/details/45057689 乍看起来,move语义使得你可以用廉价的move赋值替代昂贵的copy赋值,完美转发使得你可以将传来的任意参数转发给 其他函数,而右值引用使得move语义和完美转发成为可能.然而,慢慢地你发现这不那么简单,你发现std::move并没有move任何东西,完美转发也并不完美,而T&&也不一定就是右值引用-- move语义 最原始的左值