设为首页 加入收藏

TOP

右值引用和移动语义(二)
2019-07-08 12:10:08 】 浏览:91
Tags:引用 移动 语义
ut << std::endl; } void Useless::ShowObject() const { std::cout << "Number of elements: " << n; std::cout << " Data address: " << (void *)pc << std::endl; }
#include"Useless.h"
#include<utility>

int main()
{
    {
        Useless one(10, 'x');
        Useless two = one;  //深拷贝
        Useless three(20, '0');
        Useless four(one + three);  //operator+()
        std::cout << "object one: ";
        one.ShowData();
        std::cout << "object two: ";
        two.ShowData();
        std::cout << "object three: ";
        three.ShowData();
        std::cout << "object four: ";
        four.ShowData();
    }
    system("pause");
    return 0;
}
首先看下复制构造函数
Useless two = one;把one对象(左值)赋给了two,在这期间会调用复制构造函数Useless(const Useless& f)来实现复制;
再来看看Useless four(one + three)这条语句,one+three会调用operatoe+()来产出了一个右值,这个右值作为参数调用了Useless(Useless && f)这个构造函数,
我们称其为移动构造函数(你没有提供的话系统会提供一个默认的移动构造函数)

现在再深入探究下一些函数的具体实现:

一丶首先把移动构造函数的声明和定义注释掉

1.首先参数one+three里面调用一个构造函数创建一个temp对象,然后通过一个复制构造函数来创建一个临时复制对象,然后指向了这个对象(即函数返回了这个临时对象);接下来,删除这个temp对象;

Useless Useless::operator+(const Useless & f) const
{
    ......
    Useless temp = Useless(n + f.n);
    for (int i = 0; i < n; i++)
        temp.pc[i] = pc[i];
    for (int i = n; i < temp.n; i++)
        temp.pc[i] = f.pc[i - n];
    ......
    return temp;
}

2.因为常量左值引用可以绑定右值,所以会调用下面这个函数

Useless::Useless(const Useless & f):n(f.n)
{
    .....
    pc = new char[n];
    for (int i = 0; i < n; i++)
        pc[i] = f.pc[i];
    .......
}

所以会新建一个four对象.使其使用这个临时对象中的内存,接下来删除了这个临时对象

这个表明了总共创建了三个对象

二丶把移动构造函数的声明和定义的注释取消掉

1.这个one+three同样调用了operator+()这个函数

2.(1)因为参数one+three是个临时对象,是个右值,所以编译器会先调用移动构造函数而不是复制构造函数

(2)与复制构造函数不同的是,他直接指向了这个临时对象,然后把原来指向这个临时对象的指针改为nullptr(相当于一个对象的所有权的转移,把临时对象的所以权夺了过来)

(3)把原来指向临时对象的指针改为nullptr是让这个对象析构不会使原来的内存被释放掉,不然这个移动构造函数没有意义

这样便省去了复制构造函数中创建一个临时对象的过程,总共创建了两个对象;

而移动语义目的之一就是消除这些额外的工作.

一旦工作量变大,就会导致一些额外的资源申请和释放的操作;使用移动语音就既能够够节省资源,也能够节省时间

当然除了移动构造函数,还有移动赋值函数(在这里就不讲了,大致原理是一样的

std::move()

std::move()在头文件utility

有时候左值是一个局部变量,即表明他也是有临时的生命周期,那么能不能也是调用移动语义而不是复制语义呢?

c++11提供了std::move()来解决这个问题,他可以把左值强制转化为右值引用,使左值可用于移动语义中

Useless four(one);  //调用复制构造函数
Useless four(std::move(one));  //调用移动构造函数 

如果我们没有提供移动构造函数,std::move()会失效但不会报错,因为会调用复制构造函数(const &)

可能有待续写......

首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇DFS和BFS的比较 下一篇BFS(二):数的变换

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目