C++11:移动语义和完美转发


拷贝构造和移动构造对比

拷贝构造

代码1:

#include <iostream>
using namespace std;

class HasPtrMem {
public:
    HasPtrMem() : d(new int(0)) {
        cout << "Construct: " << ++n_cstr << endl;
    }

    HasPtrMem(const HasPtrMem &rhs) : d(new int(*rhs.d)) {
        cout << "Copy Construct: " << ++n_cpstr << endl;
    }

    ~HasPtrMem() {
        delete d;
        d = nullptr;
        cout << "Destruct: " << ++n_dstr << endl;
    }

    int *d;
    static int n_cstr;
    static int n_dstr;
    static int n_cpstr;
};

int HasPtrMem::n_cstr = 0;
int HasPtrMem::n_dstr = 0;
int HasPtrMem::n_cpstr = 0;

HasPtrMem getTemp()
{
    return HasPtrMem();
}

int main()
{
    HasPtrMem a = getTemp();
    return 0;
}

这个程序应该输出

Construct: 1        // getTemp函数中的HasPtrMem()表达式显示调用构造函数,生成临时变量temp
Copy Construct: 1   // 从临时变量temp拷贝构造出一个临时值来作为getTemp函数的返回值
Destruct: 1         // temp析构
Copy Construct: 2   // main中从getTemp函数的返回值拷贝构造出a
Destruct: 2         // getTemp函数的返回值析构
Destruct: 3         // a析构

进行了两次拷贝构造。如果HasPtrMem的指针指向非常大的堆内存数据的话,那么拷贝构造的过程就会非常昂贵。

实际在VS2013环境下输出

Construct: 1
Destruct: 1

这是因为编译器对函数返回值作了优化,即RVO(Return Value Optimization)。

移动构造

移动构造:在构造时使得临时对象的堆内存资源直接“移动”到对象a下,同时保证临时对象不释放其所指向的堆内存。这样在构造完成后,临时对象被析构,a就得到了临时对象所拥有的堆内存资源。

这里写图片描述

代码2:

#include <i
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值