IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c++ 移动语义与拷贝 -> 正文阅读

[C++知识库]c++ 移动语义与拷贝

移动语义:

传统 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

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-11 21:57:07  更:2022-03-11 21:58:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:35:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码