C++之浅拷贝、深拷贝、拷贝构造函数、拷贝赋值运算符、自定义的深拷贝函数应用总结(二百二十九)

2023-09-21 22:11:49

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

1.前言

本篇目的:理解C++之拷贝类对象到this指针应用。

  1. 浅拷贝(Shallow Copy):
    浅拷贝是指简单地复制对象的成员变量的值。在浅拷贝中,只复制指针或基本数据类型的值,而不会创建新的动态内存或复制指针所指向的数据。这导致多个对象共享相同的内存,可能引发潜在的问题,例如内存释放或修改数据时的冲突。

  2. 深拷贝(Deep Copy):
    深拷贝是指复制整个对象及其动态分配的内存。在深拷贝中,会创建一个新的对象,并为新对象的成员变量分配独立的内存,以复制原始对象的数据。这样可以确保每个对象拥有独立的内存空间,从而避免了共享数据的问题。

  3. 拷贝构造函数(Copy Constructor):
    拷贝构造函数是类的特殊成员函数,用于创建一个新对象,该新对象是通过复制现有对象的数据来初始化的。拷贝构造函数通常以引用形式接受一个同类型的对象作为参数,并从参数对象中复制数据到新对象。拷贝构造函数常用于对象的初始化、传递对象给函数或返回对象时进行复制操作。

  4. 拷贝赋值运算符(Copy Assignment Operator):
    拷贝赋值运算符是另一个特殊成员函数,用于将一个对象的数据复制给另一个已存在的对象。通常以赋值运算符(=)表示,并在函数体内执行适当的数据复制操作。拷贝赋值运算符允许对象之间完成数据的拷贝和替换,使一个对象能够取代另一个对象的数据。

  5. 自定义的深拷贝函数(Custom Deep Copy Function):
    自定义的深拷贝函数是用户自行编写的函数,用于实现对于类对象的深度复制。这种函数通常通过自己分配新的内存,并复制原始对象的成员变量内容到新分配的内存中。自定义的深拷贝函数可以在没有默认的拷贝构造函数或拷贝赋值运算符的情况下,实现深度复制。

  6. 通过指针进行拷贝(Copy by Pointer):
    通过指针进行拷贝是一种在类的拷贝操作中,复制指针本身的值,而不是复制指针指向的数据。这意味着多个指针将指向相同的数据,从而可能导致数据修改引起的冲突。这种方式通常不是推荐的拷贝方式,除非确保指向的数据不会在拷贝对象之间发生改变。

  7. 移动语义(Move Semantics):
    移动语义是一种优化技术,用于在对象转移时避免不必要的内存复制。通过使用移动构造函数和移动赋值运算符,对象的资源(如动态分配的内存)可以在转移后被接收方使用,而不需要进行复制。这在提高程序性能和减少资源占用方面是有益的。

2.应用实例

v1.0 浅拷贝

#include <iostream>

class MyClass {
public:
    int value;

    MyClass(int val = 0) : value(val) {}

    void printValue() const {
        std::cout << "Value: " << value << std::endl;
    }
};

int main() {
    MyClass obj1(10);
    MyClass obj2 = obj1; // 浅拷贝

    obj1.printValue(); // 输出: Value: 10
    obj2.printValue(); // 输出: Value: 10

    return 0;
}

v2.0 深拷贝

#include <iostream>
#include <cstring> // for memcpy

class MyClass {
public:
    int* value;

    MyClass(int val = 0) {
        value = new int(val);
    }

    ~MyClass() {
        delete value;
    }

    MyClass(const MyClass& other) {
        value = new int;
        memcpy(value, other.value, sizeof(int));
    }

    void printValue() const {
        std::cout << "Value: " << *value << std::endl;
    }
};

int main() {
    MyClass obj1(10);
    MyClass obj2 = obj1; // 深拷贝

    obj1.printValue(); // 输出: Value: 10
    obj2.printValue(); // 输出: Value: 10

    return 0;
}

v3.0 拷贝构造函数

#include <iostream>

class MyClass {
public:
    int value;

    MyClass(int val = 0) : value(val) {}

    MyClass(const MyClass& other) : value(other.value) {}

    void printValue() const {
        std::cout << "Value: " << value << std::endl;
    }
};

int main() {
    MyClass obj1(10);
    MyClass obj2(obj1); // 使用拷贝构造函数

    obj1.printValue(); // 输出: Value: 10
    obj2.printValue(); // 输出: Value: 10

    return 0;
}

4.0 拷贝赋值运算符

#include <iostream>

class MyClass {
public:
    int value;

    MyClass(int val = 0) : value(val) {}

    MyClass& operator=(const MyClass& other) {
        if (this != &other) {
            value = other.value;
        }
        return *this;
    }

    void printValue() const {
        std::cout << "Value: " << value << std::endl;
    }
};

int main() {
    MyClass obj1(10);
    MyClass obj2;
    obj2 = obj1; // 使用拷贝赋值运算符

    obj1.printValue(); // 输出: Value: 10
    obj2.printValue(); // 输出: Value: 10

    return 0;
}

v5.0 自定义的深拷贝函数

#include <iostream>

class MyClass {
public:
    int* value;

    MyClass(int val = 0) {
        value = new int(val);
    }

    ~MyClass() {
        delete value;
    }

    void deepCopyFrom(const MyClass& other) {
        *value = *other.value;
    }

    void printValue() const {
        std::cout << "Value: " << *value << std::endl;
    }
};

int main() {
    MyClass obj1(10);
    MyClass obj2;
    obj2.deepCopyFrom(obj1); // 使用自定义的深拷贝函数

    obj1.printValue(); // 输出: Value: 10
    obj2.printValue(); // 输出: Value: 10

    return 0;
}

v6.0 通过指针进行拷贝

#include <iostream>

class MyClass {
public:
    int* value;

    MyClass(int val = 0) {
        value = new int(val);
    }

    MyClass(const MyClass& other) {
        value = new int(*other.value);
    }

    ~MyClass() {
        delete value;
    }

    void printValue() const {
        std::cout << "Value: " << *value << std::endl;
    }
};

int main() {
    MyClass obj1(10);
    MyClass obj2 = obj1; // 通过指针进行拷贝

    obj1.printValue(); // 输出: Value: 10
    obj2.printValue(); // 输出: Value: 10

    return 0;
}

v7.0 移动语义

#include <iostream>

class MyClass {
public:
    int* value;

    MyClass(int val = 0) {
        value = new int(val);
    }

    MyClass(MyClass&& other) : value(other.value) {
        other.value = nullptr;
    }

    ~MyClass() {
        delete value;
    }

    void printValue() const {
        std::cout << "Value: " << *value << std::endl;
    }
};

int main() {
    MyClass obj1(10);
    MyClass obj2 = std::move(obj1); // 移动语义

    obj1.printValue(); // 这里会输出一个未定义的值(因为已移动)
    obj2.printValue(); // 输出: Value: 10

    return 0;
}

v8.0 将对象other的内容复制到当前对象中(即this指针)

```cpp
#include <iostream>
#include <cstring>

class MyClass {
public:
    int value;

    void copyFrom(const MyClass& other) {
        memcpy(this, &other, sizeof(MyClass));
    }
};

int main() {
    MyClass obj1;
    obj1.value = 10;

    MyClass obj2;
    obj2.copyFrom(obj1);

    std::cout << "obj2.value: " << obj2.value << std::endl;

    return 0;
}

1.优点:
使用memcpy函数将&other对象的内存内容复制到this指针所指向的内存中。这样做的目的是实现对象之间的值复制,包括成员变量的值以及可能存在的虚函数表指针等。

2.缺点:
虽然使用memcpy可以将对象的内存内容直接复制到目标对象,但这种方式可能会导致未定义行为。这是因为memcpy是对内存进行字节级别的复制,无法处理对象中的特殊情况,如动态分配的内存、虚函数表指针等。因此,对于自定义的类,更推荐使用逐个复制成员变量的方式来实现对象之间的值复制,以确保复制的正确性和安全性。例如:

void copyFrom(const MyClass& other) {
    this->value = other.value;
    // 在实际的代码中,可能还需要逐个复制其他成员变量
}
更多推荐

传感器浮点数数据在串口通信中封包技术解析

一、项目实现要求根据项目要求,我们需要在多台机器人间进行数据通信,系统搭建如下:在机器人A上搭载大气压模块传感器和zigbee通信模块,在机器人B上搭载手势传感器和zigbee通信模块,在机器人C上搭载zigbee通信模块,要求A和B的传感器数据能够通过zigbee模块传输到机器人C并用以做进一步的控制处理。二、由于分

word的分隔符和分页符

目录1.word中的分隔符和分页有何不同2.word中我想把表格所在的页设置为横向,上下页均为纵向3.表格页末尾的光标回车生成新的页面后,其仍然为横向,而我希望它为纵向1.word中的分隔符和分页有何不同分隔符和分页符在Word中都是用于文本分段的工具,但它们的用途和操作方式有所不同。分隔符是一个广义的概念,包括分页符

MYSQL的锁

概述锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更

LVS 负载均衡集群的DR模式配置

集群集群的概述集群技术是一种用于提高系统性能、可用性、容错性和可扩展性的关键方法。它涉及将多个计算资源或节点组合在一起,以协同工作以处理任务、服务请求或数据处理。集群类型无论是哪种集群,都至少包括两台节点服务器,而对外表现成一个整体,只提供一项服务,相当于一台大型计算机。根据群集所针对的目标差异,可分为三种类型的集群负

分布式ETL工具Sqoop实践

Mysql数据准备1、在node02节点登录Mysql。mysql-uroot-proot2、新建数据库testdb。createdatabasetestdb;3、新建数据表ts。usetestdb;createtablets(idint,namevarchar(10),ageint,sexchar(1));4、向表中

hive中的索引

使用索引前的配置在使用Hive索引之前,需要进行一些配置,以确保索引能够正常工作。以下是一些常见的配置步骤:Hive配置在Hive中启用索引功能,需要在Hive配置文件(hive-site.xml)中设置以下属性:<property><name>hive.index.compact.file.uris</name><v

【日记】文章更新计划

有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top文章最后有详细的更新计划{%timeline2023,pink%}第一版发布【完结~开发规范系列】Linux系列重新定位,不再只是简单的说常用命令周二rocketmq更换为nginx系列微服务内容变

好用的一站式MES系统有哪些?全面管理生产流程,实现工厂数字化转型

在现代制造业中,MES制造执行系统已经成为了不可或缺的信息化工具。它为企业建立了规范化、集成化的生产信息管理平台,通过集成管理思想,帮助企业优化流程管控、数字化生产车间,从而显著提升了生产效率。那么,MES系统到底可以为企业解决哪些问题呢?2023年制造工厂生产管理现状信息化现状:许多企业使用ERP系统来管理业务流程,

操作系统权限提升(二十七)之数据库提权-MySQL MOF提权

MySQLMOF提权MOF介绍mof是windows系统的一个“托管对象格式”文件(位置:C:/windows/system32/wbem/mof/),其作用是每隔五秒就会去监控进程创建和死亡,mof目录下有两个文件夹(good与bad)。Windowsserver2003及以下系统每5秒会执行一次mof目录下的文件,

百度SEO不稳定的原因及解决方法(百度SEO不稳定因素的5大包括)

百度SEO优化不稳定介绍:蘑菇号-www.mooogu.cn随着百度SEO算法的不断变化和升级,许多网站的SEO排名经常出现不稳定的情况,这种情况在一定程度上影响了网站的流量和排名,导致网站的质量评分降低。因此,深入分析百度SEO不稳定的原因和解决方法非常必要。百度SEO不稳定因素的5大包括:1.网站内容和质量不佳,没

day06_Java中的流程控制语句

流程控制简单来讲所谓流程就是完成一件事情的多个步骤组合起来就叫做一个流程。在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的。我们必须清楚每条语句的执行流程。而且,很多时候要通过控制语句的执行顺序来实现我们想要的功能。流程控制语句分为:顺序结构丶分支结构(if,switch)丶循环结构(for,whi

热文推荐