day09了 加油

news2024/11/23 2:29:13

浅拷贝 指向同一个地址空间

右边不可取地址 左边一定是到了具体的位置

右值引用std:: move

相信大家默认构造函数都没有问题,所以就不贴例子了

浅拷贝构造函数

只负责复制地址,而不是真的把完整的内存给它

#include <iostream>

// 浅拷贝是通过默认的复制构造函数来实现的。默认的复制构造函数会逐个复制对象的所有成员变量,但不会复制动态分配的内存。浅拷贝只是复制指针而不复制指针指向的内容。

class Shallow {
public:
    int* data;
    
    // 构造函数
    Shallow(int d) {
        data = new int(d);
    }

    // 浅拷贝构造函数
    Shallow(const Shallow& source) : data(source.data) {
        std::cout << "Shallow copy constructor - shallow copy" << std::endl;
    }

    // 析构函数
    ~Shallow() {
        delete data;
        std::cout << "Destructor freeing data" << std::endl;
    }
};

int main() {
    Shallow obj1(42);
    Shallow obj2 = obj1; // 使用浅拷贝构造函数

    std::cout << "obj1 data: " << *obj1.data << std::endl;
    std::cout << "obj2 data: " << *obj2.data << std::endl;

    return 0;
}

深拷贝构造函数

其实跟深拷贝的意思一样,真正的什么都复制

还要分配新的内存

#include <iostream>

class Deep {
public:
    int* data;

    // 构造函数
    Deep(int d) {
        data = new int(d);
    }

    // 深拷贝构造函数
    Deep(const Deep& source) {
        data = new int(*source.data);
        std::cout << "Deep copy constructor - deep copy" << std::endl;
    }

    // 析构函数
    ~Deep() {
        delete data;
        std::cout << "Destructor freeing data" << std::endl;
    }
};

int main() {
    Deep obj1(42);
    Deep obj2 = obj1; // 使用深拷贝构造函数

    std::cout << "obj1 data: " << *obj1.data << std::endl;
    std::cout << "obj2 data: " << *obj2.data << std::endl;

    return 0;
}

浅拷贝构造函数的代码会遇到一个问题,就是出现悬空指针,析构的时候会指向同一个指针

而深拷贝就避免了这个问题

为了提升性能,因此就来了新的概念 

移动语义

用移动构造函数和移动赋值运算符。

移动构造函数(Move Constructor)是C++11引入的一种特殊构造函数,

用于实现对象资源的高效转移,而不是复制。

它的引入是为了避免不必要的深拷贝,提高程序性能,特别是当处理临时对象时。

移动构造函数的概念

  • 移动构造函数允许从一个即将销毁的对象(通常是临时对象)中“窃取”资源,而不是复制资源。
  • 移动构造函数接收一个右值引用参数,即将被移动的对象,并将其资源转移到新对象中。
  • 移动构造函数通常与移动赋值运算符一起使用,以实现全面的移动语义。

这里建议直接看例子

移动构造函数的语法

移动构造函数的声明使用右值引用参数(通常是 Type&&,并在实现中转移资源。

#include <iostream>

class Mstring {
public:
    char* data;

    // 默认构造函数
    Mstring() : data(nullptr) {
        std::cout << "Default constructor called" << std::endl;
    }

    // 参数构造函数
    Mstring(const char* str) {
        if (str) {
            data = new char[strlen(str) + 1];
            strcpy(data, str);
        } else {
            data = nullptr;
        }
        std::cout << "Parameterized constructor called" << std::endl;
    }

    // 拷贝构造函数
    Mstring(const Mstring& source) {
        if (source.data) {
            data = new char[strlen(source.data) + 1];
            strcpy(data, source.data);
        } else {
            data = nullptr;
        }
        std::cout << "Copy constructor called" << std::endl;
    }

    // 移动构造函数
    Mstring(Mstring&& source) noexcept : data(source.data) {
        source.data = nullptr;
        std::cout << "Move constructor called" << std::endl;
    }

    // 拷贝赋值运算符
    Mstring& operator=(const Mstring& source) {
        if (this == &source)
            return *this;

        delete[] data;
        if (source.data) {
            data = new char[strlen(source.data) + 1];
            strcpy(data, source.data);
        } else {
            data = nullptr;
        }
        std::cout << "Copy assignment operator called" << std::endl;
        return *this;
    }

    // 移动赋值运算符
    Mstring& operator=(Mstring&& source) noexcept {
        if (this == &source)
            return *this;

        delete[] data;
        data = source.data;
        source.data = nullptr;
        std::cout << "Move assignment operator called" << std::endl;
        return *this;
    }

    // 析构函数
    ~Mstring() {
        delete[] data;
        std::cout << "Destructor called" << std::endl;
    }
};

int main() {
    Mstring str1("Hello");
    Mstring str2("World");

    // 使用移动赋值运算符
    str2 = std::move(str1);

    std::cout << "After move assignment, str1: " << (str1.data ? str1.data : "nullptr") << std::endl;
    std::cout << "After move assignment, str2: " << (str2.data ? str2.data : "nullptr") << std::endl;

    return 0;
}

参数构造函数

参数构造函数是C++类的一种构造函数,

它接受一个或多个参数,

并使用这些参数来初始化类的成员变量。

与默认构造函数(不接受任何参数)相对,

参数构造函数为类的实例提供了一种灵活的初始化方式。

参数构造函数的定义

参数构造函数是在类的定义中声明的构造函数,

其参数列表可以包含一个或多个参数。

通过这些参数,构造函数可以对类的成员变量进行初始化。上面的例子是有体现的

  • 默认构造函数Mstring(),不接受任何参数,初始化成员变量 datanullptr
  • 参数构造函数Mstring(const char* str),接受一个 const char* 参数,用于初始化成员变量 data。如果参数不为空,则分配足够的内存并复制字符串内容。
  • 拷贝构造函数Mstring(const Mstring& source),用于创建一个现有对象的副本,分配新的内存并复制内容。
  • 移动构造函数Mstring(Mstring&& source) noexcept,用于高效地从另一个即将销毁的对象中移动资源,避免了不必要的内存分配和复制。
  • 拷贝赋值运算符:用于将一个对象的内容赋值给另一个现有对象,确保正确地处理动态分配的内存。
  • 移动赋值运算符:用于将一个即将销毁的对象的内容移动到另一个现有对象,避免不必要的内存分配和复制。
  • 析构函数~Mstring(),释放动态分配的内存,避免内存泄漏。
  • main 函数:演示如何使用参数构造函数创建对象,以及如何使用移动构造函数进行对象移动。

内存提前分配

内存提前分配(Pre-allocation)是指在对象或数据结构初始化时提前分配所需的内存,以减少运行时的分配开销。这在需要处理大量数据或频繁分配和释放内存的场景中特别有用。

参数构造函数中的内存提前分配示例

下面是一个改进的 Mstring 类,展示了如何在参数构造函数中提前分配内存。

#include <iostream>

class Array {
private:
    int* data;
    size_t size;

public:
    // 参数构造函数:提前分配内存
    Array(size_t size) : size(size) {
        data = new int[size]; // 提前分配内存
        std::cout << "Constructor: Allocated memory for " << size << " integers." << std::endl;
    }

    // 析构函数:释放内存
    ~Array() {
        delete[] data;
        std::cout << "Destructor: Freed allocated memory." << std::endl;
    }

    // 获取数组大小
    size_t getSize() const {
        return size;
    }

    // 获取数组元素(带边界检查)
    int getElement(size_t index) const {
        if (index < size) {
            return data[index];
        } else {
            throw std::out_of_range("Index out of range");
        }
    }

    // 设置数组元素(带边界检查)
    void setElement(size_t index, int value) {
        if (index < size) {
            data[index] = value;
        } else {
            throw std::out_of_range("Index out of range");
        }
    }
};

int main() {
    // 使用参数构造函数创建一个大小为10的数组
    Array arr(10);

    // 设置数组中的元素
    for (size_t i = 0; i < arr.getSize(); ++i) {
        arr.setElement(i, i * 2);
    }

    // 获取并打印数组中的元素
    for (size_t i = 0; i < arr.getSize(); ++i) {
        std::cout << "Element at index " << i << ": " << arr.getElement(i) << std::endl;
    }

    // arr对象超出作用域时,会自动调用析构函数释放内存
    return 0;
}

内存重复利用

1.分配一块内存2构建对象3使用对象4析构对象5销毁内存

1.优先使用dowhile循环

压栈的开销非常大,因此避免重复调用

面向对象和面向过程的区别

面向过程和面向对象的区别-CSDN博客

什么是内联函数

函数移除不必要的多态性 减省空间

性能在面向对象中最顶的

swich 跳转很快

简化表达式+位移算法

IO优化

Vector

list

set/multiset

map/Multiset

选择策略

性能分析工具

Asan

实现原理: 编译的时候。。。方式

Gprof

Valgrind

Perf

能看到函数调用次数

系统资源对性能的影响

进程选取

更新当前任务虚拟时间

异构cpu+多频率带

内存管理

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

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

相关文章

Qt——升级系列(Level Seven):事件、文件

目录 Qt事件 事件介绍 事件的处理 按键事件 鼠标事件 定时器 事件分发器 事件过滤器 Qt文件 Qt文件概述 输入输出设备类 文件读写类 文件和目录信息类 Qt事件 事件介绍 事件是应⽤程序内部或者外部产⽣的事情或者动作的统称。在 Qt 中使⽤⼀个对象来表⽰⼀个事件。所有的 Qt …

Linux修炼之路之进程概念,fork函数,进程状态

目录 一&#xff1a;进程概念 二&#xff1a;Linux中的进程概念 三&#xff1a;用getpid(),getppid()获取该进程的PID,PPID 四&#xff1a;用fork()来创建子进程 五&#xff1a;操作系统学科的进程状态 六&#xff1a;Linux中的进程状态 接下来的日子会顺顺利利&#xf…

WordPress网站添加插件和主题时潜在危险分析

WordPress 最初只是一个简单的博客软件&#xff0c;现在据估计为全球前 1000 万个网站中的 30% 提供支持。WordPress受欢迎的因素之一是可以轻松创建插件和主题来扩展它并提供比默认设置更多的功能。 目前&#xff0c;WordPress 网站列出了 56,000 多个插件以及数千个主题。插件…

提升用户体验之requestAnimationFrame实现前端动画

requestAnimationFrame是什么 MDN官方解释 解析这段话&#xff1a; 1、那么浏览器重绘是指什么呢&#xff1f; ——大多数电脑的显示器刷新频率是60Hz&#xff0c;1000ms/6016.66666667ms的时间刷新一次 2、重绘之前调用指定的回调函数更新动画&#xff1f; ——requestAnima…

机器学习辅助的乙醇浓度检测

目录 1.为什么要机器学习 2. 神经网络一般组成 3.BP神经网络工作过程 4.评价指标 5.实操代码 1.为什么要用机器学习 人工分析大量的谐振模式&#xff0c;建立各种WGM的响应与未知目标之间的关系&#xff0c;是一个很大的挑战。机器学习(ML)能够自行识别全谱的全部特征。作为…

Python深度理解系列之【排序算法——冒泡排序】

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️木道寻的主页 文章目录 &#x1f525;前言&#x1f680;冒泡排序python实现算法实现图形化算法展示 ⭐️⭐️⭐️总结 &#x1f525;前…

ONLYOFFICE8.1版本桌面编辑器简单测评

ONLYOFFICE官网链接&#xff1a;在线PDF查看器和转换器 | ONLYOFFICE ONLYOFFICE介绍&#xff1a;https://www.onlyoffice.com/zh/office-suite.aspx OnlyOffice 是一款免费且开源的 Office 协作办公套件&#xff0c;支持桌面端和移动端等多平台&#xff0c;由一家领先的 IT 公…

OpenStack开源虚拟化平台(二)

目录 三、对象存储服务Swift&#xff08;一&#xff09;Swift特性&#xff08;二&#xff09;应用场景&#xff08;三&#xff09;Swift主要组件&#xff08;四&#xff09;Swift基本原理&#xff08;五&#xff09;实例分析 四、镜像服务Glance&#xff08;一&#xff09;Glan…

如何在 Java 应用中使用 Jedis 客户端库来实现 Redis 缓存的基本操作

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

图解 Kafka 架构

写在前面 Kafka 是一个可横向扩展&#xff0c;高可靠的实时消息中间件&#xff0c;常用于服务解耦、流量削峰。 好像是 LinkedIn 团队开发的&#xff0c;后面捐赠给apache基金会了。 kafka 总体架构图 Producer&#xff1a;生产者&#xff0c;消息的产生者&#xff0c;是消息的…

不改代码,实现web.config或app.config的连接字符串加密解密

目的&#xff1a;加密字符串&#xff0c;防止明文显示。 好处&#xff1a;不用修改代码&#xff0c;微软自带功能&#xff0c;自动解密。 web.config 参考相关文章&#xff1a; Walkthrough: Encrypting Configuration Information Using Protected Configuration | Microso…

本地通过ollama下载模型,并使用python跑这个本地模型

1&#xff0c;这是ollama地址&#xff0c;下载对应的安装包 https://ollama.com/?viaurlainavpro.com 2&#xff0c;下载完直接安装即可&#xff0c;安装完后&#xff0c;winr打开cmd&#xff0c;出现这个&#xff0c;基本就妥了 3&#xff0c;这里我们需要去下载模型&#x…

笔记:Git学习之应用场景和使用经验

目标&#xff1a;整理Git工具的应用场景和使用经验 一、开发环境 Git是代码版本控制工具&#xff1b;Github是代码托管平台。 工具组合&#xff1a;VSCode Git 需要安装的软件&#xff1a;vscode、Git 其中vscode需要安装的插件&#xff1a;GitLens、Git History 二、应用…

【NLP学习笔记】load_dataset加载数据

除了常见的load_dataset(<hf上的dataset名>)这种方式加载HF上的所有数据外&#xff0c;还有其他custom的选项。 加载HF上部分数据 from datasets import load_dataset c4_subset load_dataset("allenai/c4", data_files"en/c4-train.0000*-of-01024.js…

PowerBi 获取指定时间间隔的日期的方法

获取指定时间间隔的日期&#xff0c;比如我们想得到2024年5月31日后的第三天。 网络上的教程一般是使用DATEADD()函数。 但是这个函数返回的是表。假如我们的需求是不做汇总等计算&#xff0c;只是把它作为一个计算列&#xff0c;或者度量值&#xff0c;那么我更推荐用DATE(&…

webstorm 高效查看不同分支差异 摒弃你的git diff手动操作

背景 每次代码冲突或者版本发生异常时&#xff0c;排查不同版本时就是一个头大的问题&#xff0c;头大的点在于用 vscode 的 git diff 一点点地排查和比较&#xff0c;耗时耗力&#xff0c;版面展不开&#xff0c;commit 差异看不出来&#xff0c;每个页面的代码不同也不能快速…

【Java08】方法(上)

从面向对象的角度来看&#xff0c;Java中的方法是类或对象行为的抽象。但和C不同&#xff0c;Java中”剔除“了C中”残留“的结构化编程。具体地说&#xff0c;Java中的方法必须在类中定义&#xff0c;没有独立存在的函数。 也有人把结构化编程&#xff0c;叫做”面向函数的编程…

Linux基础指令介绍与详解——原理学习

前言&#xff1a;本节内容标题虽然为指令&#xff0c;但是并不只是讲指令&#xff0c; 更多的是和指令相关的一些原理性的东西。 如果友友只想要查一查某个指令的用法&#xff0c; 很抱歉&#xff0c; 本节不是那种带有字典性质的文章。但是如果友友是想要来学习的&#xff0c;…

基于FPGA的DDS信号发生器

前言 此处仅为基于Vivado实现DDS信号发生器的仿真实现&#xff0c;Vivado的安装请看下面的文章&#xff0c;这里我只是安装了一个标准版本&#xff0c;只要能够仿真波形即可。 FPGA开发Vivado安装教程_vivado安装 csdn-CSDN博客 DDS原理 DDS技术是一种通过数字计算生成波形…

Linux shell编程学习笔记61: pstree 命令——显示进程树

0 前言 在 Linux shell编程学习笔记59&#xff1a; ps 获取系统进程信息&#xff0c;类似于Windows系统中的tasklist 命令https://blog.csdn.net/Purpleendurer/article/details/139696466?spm1001.2014.3001.5501 中我们研究了ps命令。在Linux中&#xff0c;通过ps命令&am…