c++移动构造函数是什么?

移动构造函数是什么?
移动构造是C++11标准中提供的一种新的构造方法。
先举个生活例子,你有一本书,你不想看,但我很想看,那么我有哪些方法可以让我能看这本书?有两种做法,一种是你直接把书交给我,另一种是我去买一些稿纸来,然后照着你这本书一字一句抄到稿纸上。
显然,第二种方法很浪费时间,但这正是有些深拷贝构造函数的做法,而移动构造函数便能像第一种做法一样省时,第一种做法在 C++ 中叫做完美转发。

在C++11之前,如果要将源对象的状态转移到目标对象只能通过复制。
而现在在某些情况下,我们没有必要复制对象,只需要移动它们。

C++11引入移动语义:
源对象资源的控制权全部交给目标对象。

拷贝构造和移动构造对比
拷贝构造是这样的:
在对象被复制后临时对象和拷贝构造的对象各自占有不同的同样大小的堆内存,就是一个副本。
从下图中可以看到,临时对象和新建对象a申请的堆内存同时存在。

14bea0d8945742d2afae4d77bd58a5f8.png

 移动构造是这样的:
就是让这个临时对象它原本控制的内存的空间转移给构造出来的对象,这样就相当于把它移动过去了。
从下图中可以看到,原本由临时对象申请的堆内存,由新建对象a接管,临时对象不再指向该堆内存。

c55e5d0a714e464e8bed3fb4a88cc89b.png

 

改进的拷贝构造
设想一种情况,我们用对象a初始化对象b,后对象a我们就不在使用了,但是对象a的空间还在呀(在析构之前),既然拷贝构造函数,实际上就是把a对象的内容复制一份到b中,那么我们可以对指针进行浅复制,这样就避免了新的空间的分配,大大降低了构造的成本。
但是我们知道,指针的浅层复制是非常危险的,浅层复制之所以危险,是因为两个指针共同指向一片内存空间,若第一个指针将其释放,另一个指针的指向就不合法了(常出现二次释放错误)。所以我们只要避免第一个指针释放空间就可以了。避免的方法就是将第一个指针(比如a->value)置为NULL,这样在调用析构函数的时候,由于有判断是否为NULL的语句,所以析构a的时候并不会回收a->value指向的空间(同时也是b->value指向的空间),注意,即使没有判断NULL的语句,直接delete null也是不会发生什么事的。

#include <iostream>
#include <string>

using namespace std;

class Integer 
{
private:
    int *m_ptr;
public:
    Integer(int value) : m_ptr(new int(value)) 
    {
        cout << "带参数构造函数" << endl;
    }
    //参数为常量左值引用的深拷贝构造函数,不改变 source.ptr_ 的值
    Integer(const Integer &source) : m_ptr(new int(*source.m_ptr)) 
    {
        cout << "参数为常量左值引用的深拷贝构造函数" << endl;
    }
    //参数为左值引用的浅拷贝构造函数,转移堆内存资源所有权,改变 source.m_ptr的值 为nullptr
    Integer(Integer &source) : m_ptr(source.m_ptr) 
    {
        source.m_ptr= nullptr;
        cout << "参数为左值引用的浅拷贝构造函数" << endl;
    }
    ~Integer() 
    {
        cout << "析构函数" << endl;
        delete m_ptr;
    }

    int GetValue(void) 
    { 
        return *m_ptr; 
    }
};

Integer getNum()
{
    Integer a(100);
    return a;
}

int main(int argc, char const* argv[]) 
{
    Integer a(getNum()); 

    cout << "a=" << a.GetValue() << endl;
    cout << "-----------------" << endl;

    Integer temp(10000);
    Integer b(temp);

    cout << "b=" << b.GetValue() << endl;
    cout << "-----------------" << endl;

    return 0;

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值