对象克隆与单例模式

一、对象克隆

在 C++ 中,对象克隆通常可以借助拷贝构造函数和赋值运算符重载来实现,分为浅拷贝(默认行为)和深拷贝(需要自定义实现)。

1. 浅拷贝示例

#include <iostream>
#include <string>

class Person {
public:
    Person(const std::string& name, int age) : name(name), age(age) {}

// 编译器默认生成的拷贝构造函数实现的是浅拷贝
    Person(const Person& other) : name(other.name), age(other.age) {}

void printInfo() const {
        std::cout << "Name: " << name << ", Age: " << age << std::endl;
    }

private:
    std::string name;
    int age;
};

int main() {
    Person p1("Alice", 20);
    Person p2 = p1;  // 调用拷贝构造函数进行浅拷贝
    p2.printInfo();
    return 0;
}

在上述代码中,当使用Person p2 = p1;时,编译器会调用默认生成的拷贝构造函数,它简单地将p1对象的各成员变量的值复制给p2对象对应成员变量,对于像std::string这样的类类型(它内部已经处理好了深拷贝相关逻辑)能正常工作,但如果成员变量是指针等情况,就可能出现问题(多个对象的指针指向同一块内存区域,后续修改会相互影响),这就是浅拷贝的特点。

2. 深拷贝示例

假设Person类有一个指针成员变量指向动态分配的内存,就需要自定义拷贝构造函数和赋值运算符重载来实现深拷贝,如下:

#include <iostream>
#include <string>
#include <cstring>

class Person {
public:
    Person(const std::string& name, int age) : name(name), age(age) {
        this->hobby = new char[100];
        std::strcpy(this->hobby, "Reading");
    }

// 自定义拷贝构造函数实现深拷贝
    Person(const Person& other) : name(other.name), age(other.age) {
        this->hobby = new char[100];
        std::strcpy(this->hobby, other.hobby);
    }

// 赋值运算符重载实现深拷贝
    Person& operator=(const Person& other) {
        if (this!= &other) {
            this->name = other.name;
            this->age = other.age;
            delete[] this->hobby;
            this->hobby = new char[100];
            std::strcpy(this->hobby, other.hobby);
        }
        return *this;
    }

void printInfo() const {
        std::cout << "Name: " << name << ", Age: " << age << ", Hobby: " << hobby << std::endl;
    }

~Person() {
        delete[] hobby;
    }

private:
    std::string name;
    int age;
    char* hobby;
};

int main() {
    Person p1("Alice", 20);
    Person p2 = p1;  // 调用自定义拷贝构造函数进行深拷贝
    p2.printInfo();
    Person p3("Bob", 25);
    p3 = p1;  // 调用赋值运算符重载进行深拷贝
    p3.printInfo();
    return 0;
}

这里Person类有一个char*类型的hobby成员变量指向动态分配的内存,为了实现深拷贝,在拷贝构造函数和赋值运算符重载中都重新分配了内存,并将对应内容复制过来,避免多个对象的该指针指向同一块内存而导致修改相互影响的问题。

二、单例模式

1. 饿汉式单例模式

#include <iostream>

class Singleton {
public:
    static Singleton& getInstance() {
        return instance;
    }

void showMessage() const {
        std::cout << "This is a singleton instance." << std::endl;
    }

private:
    // 在程序启动时就创建好实例
    static Singleton instance;
    Singleton() {}  // 构造函数私有,防止外部创建实例
    Singleton(const Singleton&) = delete;  // 禁用拷贝构造函数
    Singleton& operator=(const Singleton&) = delete;  // 禁用赋值运算符
};

// 初始化静态成员变量
Singleton Singleton::instance;

int main() {
    Singleton::getInstance().showMessage();
    return 0;
}

饿汉式单例模式在程序启动时就创建好单例对象,优点是线程安全(由 C++ 语言本身保证静态变量初始化的线程安全性),缺点是如果单例对象构造比较复杂或者占用资源多,会在程序启动时就占用相应资源,即便暂时不用也会提前创建。

2. 懒汉式单例模式(线程安全版本,使用互斥锁)

#include <iostream>
#include <mutex>

class Singleton {
public:
    static Singleton& getInstance() {
        std::lock_guard<std::mutex> guard(mutex_);
        if (!instance) {
            instance = new Singleton();
        }
        return *instance;
    }

void showMessage() const {
        std::cout << "This is a singleton instance." << std::endl;
    }

private:
    static Singleton* instance;
    static std::mutex mutex_;
    Singleton() {}
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
};

// 初始化静态成员变量
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex_;

int main() {
    Singleton::getInstance().showMessage();
    return 0;
}

懒汉式单例模式是在第一次调用getInstance方法时才创建单例对象,为了保证线程安全,使用std::mutex互斥锁来保证在多线程环境下只有一个线程能创建实例。不过使用互斥锁会有一定性能开销,每次获取实例都需要获取锁判断是否已经创建。

3. 双重检查锁定(DCL)单例模式(线程安全且优化性能)

#include <iostream>
#include <mutex>

class Singleton {
public:
    static Singleton& getInstance() {
        if (!instance) {
            std::lock_guard<std::mutex> guard(mutex_);
            if (!instance) {
                instance = new Singleton();
            }
        }
        return *instance;
    }

void showMessage() const {
        std::cout << "This is a singleton instance." << std::endl;
    }

private:
    static Singleton* instance;
    static std::mutex mutex_;
    Singleton() {}
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
};

// 初始化静态成员变量
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex_;

int main() {
    Singleton::getInstance().showMessage();
    return 0;
}

双重检查锁定模式在懒汉式基础上进行优化,通过两次检查instance是否为nullptr,减少了不必要的锁竞争,提升了性能,不过要注意编译器可能的指令重排问题,在实际更严谨的实现中,可能需要使用特定的内存屏障等机制来确保正确

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/64777.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle virTualBox安装window10

一、下载windows10镜像 我下载的windows10镜像如下&#xff1a; 内部文件如下&#xff1a; 二、错误的安装方法 直接新建虚拟机&#xff0c;选择镜像文件&#xff1a; 启动虚拟机&#xff08;会一直提示没有启动设备&#xff0c;选择镜像后一直弹窗提示&#xff09; 三、正确…

四川托普信息技术职业学院教案1

四川托普信息技术职业学院教案 【计科系】 周次 第 1周&#xff0c;第1次课 备 注 章节名称 第1章 XML语言简介 引言 1.1 HTML与标记语言 1.2 XML的来源 1.3 XML的制定目标 1.4 XML概述 1.5 有了HTML了&#xff0c;为什么还要发展XML 1.5.1 HTML的缺点 1.5.2 XML的特点 1.6 X…

三维引擎cesium学习经验

三维引擎cesium学习经验&#xff1a; 1、初始化viewer对象 2、对entity的操作&#xff1a;添加&#xff0c;隐藏&#xff0c;修改&#xff0c;去除&#xff0c;居中显示 3、去除掉entity的双击事件 4、获取当前视角高度 5、获取经纬度在屏幕上的位置 6、获取三维场景屏幕中心点…

虚拟机VMware的安装问题ip错误,虚拟网卡

要么没有虚拟网卡、有网卡远程连不上等 一般出现在win11 家庭版 1、是否IP错误 ip addr 2、 重置虚拟网卡 3、查看是否有虚拟网卡 4、如果以上检查都解决不了问题 如果你之前有vmware 后来卸载了&#xff0c;又重新安装&#xff0c;一般都会有问题 卸载重装vmware: 第一…

图片和媒体资源的优化:提升Web应用性能与用户体验的关键

文章目录 前言一、为什么需要优化图片和媒体资源二、图片优化策略三、媒体资源优化策略四、案例研究&#xff1a;实际效果展示结语 前言 在现代Web开发中&#xff0c;图片和媒体资源&#xff08;如音频、视频&#xff09;的质量和加载速度对用户体验有着直接影响。高质量的媒体…

裸机LED 灯实验

G1、硬件原理分析 2、寄存器说明 a、主要配置寄存器 使能 GPIO1 时钟—CCM_CCGR1 设置 GPIO1_IO03 的复用功能—IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 配置 GPIO1_IO03—IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 设置GPIO GPIO1_GDIR 的 bit3 要设置为 1,表示输出 控制GPIO输出电平,…

LSTM长短期记忆网络

LSTM&#xff08;长短期记忆网络&#xff09;数学原理 LSTM&#xff08;Long Short-Term Memory&#xff09;是一种特殊的递归神经网络&#xff08;RNN&#xff09;&#xff0c;解决了标准RNN中存在的梯度消失&#xff08;Vanishing Gradient&#xff09; 和**梯度爆炸&#x…

FastApi教程

FastApi&#xff0c;一个用于构建 API 的现代、快速&#xff08;高性能&#xff09;的web框架。 FastApi是建立在Starlette和Pydantic基础上的&#xff0c;Pydantic是一个基于Python类型提示来定义数据验证、序列化和文档的库。Starlette是一种轻量级的ASGI框架/工具包&#x…

C++进阶-1-单继承、多继承、虚继承

C单继承详解 1. 基础概念 继承是面向对象编程中的一个核心概念&#xff0c;允许一个类&#xff08;子类或派生类&#xff09;继承另一个类&#xff08;父类或基类&#xff09;的属性和方法。单继承意味着一个类只能直接继承一个父类。这种简单的结构在许多情况下是足够的&…

C语言 文件操作——按行读写文件

目录 按行写文件 按行读文件 按行读写文件 按行写文件 int puts ( const char *s ); 将字符串 s 写入标准输出流 stdout &#xff0c;并在其后添加一个换行符 按字符串&#xff08;行&#xff09; 写 文件 int fputs ( const char *s, FILE *fp); 将字符串 s 写入 fp 所…

轻松上手:使用 Vercel 部署 HTML 页面教程

&#x1f600; 在学习前端的过程中&#xff0c;部署项目往往是一个令人头疼的问题。然而&#xff0c;Vercel 为我们提供了一个便捷且免费的解决方案。 Vercel 是一个强大的云平台&#xff0c;专门用于前端项目的部署和托管。它不仅支持多种前端框架和静态网站生成器&#xff0…

【AI系列】Paddle Speech安装指南

文章目录 环境依赖1. 安装Python1.1 下载Python安装包1.2 安装gcc1.3 安装依赖库1.4 编译和安装Python1.5 配置环境变量 2. 安装PaddlePaddle3. 安装PaddleSpeech4. 运行PaddleSpeech5. 解决常见问题5.1 错误&#xff1a;libssl.so.1.1解决方法&#xff1a; 5.2 错误&#xff1…

2-6-1 关于“QNX Neutrino 编程入门”的前言

阅读前言 本文以QNX系统官方的文档英文原版资料“Getting Started with QNX Neutrino: A Guide for Realtime Programmers”为参考&#xff0c;翻译和逐句校对后&#xff0c;对在QNX操作系统下进行应用程序开发及进行资源管理器编写开发等方面&#xff0c;进行了深度整理&…

【中标麒麟服务器操作系统实例分享】java应用DNS解析异常分析及处理

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://documentkylinos.cn 情况描述 中标麒麟服务器操作系统V7运行在 ARM虚…

StarRocks 排查单副本表

文章目录 StarRocks 排查单副本表方式1 查询元数据&#xff0c;检查分区级的副本数方式2 SHOW PARTITIONS命令查看 ReplicationNum修改副本数命令 StarRocks 排查单副本表 方式1 查询元数据&#xff0c;检查分区级的副本数 # 方式一 查询元数据&#xff0c;检查分区级的副本数…

基于Transformer的自编码器模型在故障检测中的应用

在现代工业和制造领域&#xff0c;故障检测是保证设备和生产线安全、高效运行的关键。传统的故障检测方法往往依赖于人工经验或规则&#xff0c;然而&#xff0c;这些方法的准确性和泛化能力有限。随着深度学习技术的迅速发展&#xff0c;越来越多的智能故障检测方法应运而生&a…

《XML》教案 第2章 使第4章 呈现XML文档

《XML》教案 第2章 使第4章 呈现XML文档 主讲人&#xff1a; 回顾上一章: [10分钟] 2 课程知识点讲解&#xff1a; 2 通过级联样式表转换XML文档&#xff1a;[15分钟] 3 通过可扩展样式表语言转换XML文档 &#xff1a;[5分钟] 4 嵌套 for 循环 &#xff1a;[20分钟] 5 本章总结…

HBase、Hive、Redis 和 MongoDB的对比

1. 数据库管理 操作HBaseHiveRedisMongoDB创建数据库N/A (HBase 没有数据库概念)CREATE DATABASE db_name;N/A (Redis 没有数据库命名功能)use db_name; (自动创建)查看数据库N/ASHOW DATABASES;INFO 查看全局信息show dbs;删除数据库N/ADROP DATABASE db_name CASCADE;N/Adb.…

Sigrity System Explorer Snip Via Pattern From Layout模式从其它设计中截取过孔模型和仿真分析操作指导

Sigrity System Explorer Snip Via Pattern From Layout模式从其它设计中截取过孔模型和仿真分析操作指导 Sigrity System Explorer Snip Via Pattern From Layout模式支持从其它设计中截取过孔模型用于仿真分析,同样以差分模板为例 具体操作如下 双击打开System Explorer软件…

数据结构_平衡二叉树

结点类 构造函数分为有参和无参&#xff0c;相同点都是初始化树高为1 class Node { public:int data; // 用于输出int val; // 数据域&#xff0c;用于排序int height; // 树高Node* left;Node* right;Node();Node(int v, int d);static int max(int a, int b); };Node::N…