c++ 移动语义与拷贝

本文介绍了C++中的移动语义和右值引用,如何通过右值引用实现更高效的资源转移,避免无意义的数据拷贝,提高程序性能。示例代码展示了移动构造函数在对象传递过程中的应用,以及移除移动构造函数后导致的对象拷贝情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

移动语义:

传统 C++ 通过拷贝构造函数和赋值操作符为类对象设计了拷贝/复制的概念,但为了实现对资源的移动操作, 调用者必须使用先复制、再析构的方式,否则就需要自己实现移动对象的接口。 试想,搬家的时候是把家里的东西直接搬到新家去,而不是将所有东西复制一份(重买)再放到新家、 再把原来
的东西全部扔掉(销毁),这是非常反人类的一件事情。
传统的 C++ 没有区分『移动』和『拷贝』的概念,造成了大量的数据拷贝,浪费时间和空间。 右值
引用的出现恰好就解决了这两个概念的混淆问题,例如:

移动语义:

~/test/test_10
$ cat test3.cpp
#include <iostream>

using namespace std;

class A {
    public:
        int *pointer;
        A() : pointer(new int(1))
        {
            std::cout << "构造" << pointer << std::endl;
        }

        A(const A& a) : pointer(new int(*a.pointer))
        {
            std::cout << "A(A& a)拷贝" << pointer << std::endl;
        } // 无意义的对象拷贝

        A(A&& a) : pointer(a.pointer)
        {
            a.pointer = nullptr;
            std::cout << "移动" << pointer << std::endl;
        }

        ~A()
        {
            std::cout << "析构" << pointer << std::endl;
            delete pointer;
        }
};

// 防止编译器优化
A return_rvalue(bool test)
{
    A a,b;

    if (test) {
        return a; // 等价于 static_cast<A&&>(a);
    }

    return b; // 等价于 static_cast<A&&>(b);
}

void test_1(void)
{
    cout << "++++++++++++=" << __FUNCTION__ << endl;
    A obj = return_rvalue(false);

    std::cout << "obj:" << std::endl;
    std::cout << obj.pointer << std::endl;
    std::cout << *obj.pointer << std::endl;
}

int main(int argc, char *const argv[])
{
    test_1();
    return 0;
}

编译 & 运行

 ~/test/test_10
$ g++ -std=c++11 test3.cpp
 ~/test/test_10
$ ./a.out
++++++++++++=test_1
构造0xfca030
构造0xfca050
移动0xfca050
析构0
析构0xfca030
obj:
0xfca050
1
析构0xfca050

拷贝:

 ~/test/test_10
$ cat test3.cpp
#include <iostream>

using namespace std;

class A {
    public:
        int *pointer;
        A() : pointer(new int(1))
        {
            std::cout << "构造" << pointer << std::endl;
        }

        A(const A& a) : pointer(new int(*a.pointer))
        {
            std::cout << "A(A& a)拷贝" << pointer << std::endl;
        } // 无意义的对象拷贝
#if 0
        A(A&& a) : pointer(a.pointer)
        {
            a.pointer = nullptr;
            std::cout << "移动" << pointer << std::endl;
        }
#endif
        ~A()
        {
            std::cout << "析构" << pointer << std::endl;
            delete pointer;
        }
};

// 防止编译器优化
A return_rvalue(bool test)
{
    A a,b;

    if (test) {
        return a; // 等价于 static_cast<A&&>(a);
    }

    return b; // 等价于 static_cast<A&&>(b);
}

void test_1(void)
{
    cout << "++++++++++++=" << __FUNCTION__ << endl;
    A obj = return_rvalue(false);

    std::cout << "obj:" << std::endl;
    std::cout << obj.pointer << std::endl;
    std::cout << *obj.pointer << std::endl;
}

int main(int argc, char *const argv[])
{
    test_1();
    return 0;
}

编译 & 运行

 ~/test/test_10
$ g++ -std=c++11 test3.cpp
 ~/test/test_10
$ ./a.out
++++++++++++=test_1
构造0x14c8030
构造0x14c8050
A(A& a)拷贝0x14c8070
析构0x14c8050
析构0x14c8030
obj:
0x14c8070
1
析构0x14c8070

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值