C++:当vector中存储的是自定义类型对象时注意事项

看一段代码,相关:构造函数、拷贝/移动构造函数、vector扩容、智能指针

示例

如果 std::vector 中存储的是自定义类型对象,以下代码可能会导致问题:

#include <vector>
#include <iostream>class MyClass {
public:int* data;MyClass(int value) : data(new int(value)) {}~MyClass() {delete data;}// 忘记实现拷贝构造函数或移动构造函数
};int main() {std::vector<MyClass> vec;vec.reserve(10);  // 预分配空间for (int i = 0; i < 5; ++i) {vec.emplace_back(i);  // 可能会导致问题}return 0;
}

原因:

  • MyClass 的析构函数释放了动态内存,但拷贝构造函数和移动构造函数未正确实现,导致扩容时拷贝或移动对象后,多个对象共享同一块内存。
  • 在释放旧空间时,会多次释放同一块内存,导致崩溃。

解决方案:

  • 正确实现拷贝构造函数和移动构造函数,或者使用智能指针。

在上述代码中,std::vector<MyClass> vec; 是一个以 MyClass 为元素类型的容器,在执行 vec.emplace_back(i); 时是否调用拷贝构造函数还是移动构造函数取决于 MyClass 是否支持移动语义编译器的优化行为


emplace_back(i) 的行为

vec.emplace_back(i) 会直接在 std::vector 已分配的内存中构造一个新的 MyClass 对象,而不会调用拷贝构造函数或移动构造函数。它通过传递 i 调用适配的构造函数。在你的例子中,它调用了 MyClass(int value) 构造函数。


当扩容发生时

std::vector 需要扩容时(例如,超过当前容量),会分配一块新的更大的连续内存,并将旧内存中的元素移动到新内存中。这时会发生拷贝或移动构造。

  • 如果 MyClass 支持移动构造函数,则会优先调用移动构造函数。
  • 如果 MyClass 没有定义移动构造函数,但支持拷贝构造函数,则会调用拷贝构造函数。
  • 如果 MyClass 同时不支持拷贝构造和移动构造,则会报编译错误。

编译器如何选择

1. 移动构造函数优先

如果 MyClass 定义了移动构造函数(或者编译器能够生成一个隐式移动构造函数),那么扩容时 std::vector 会调用移动构造函数。例如:

class MyClass {
public:int* data;MyClass(int value) : data(new int(value)) {}~MyClass() { delete data; }// 移动构造函数MyClass(MyClass&& other) noexcept : data(other.data) {other.data = nullptr;}// 禁用拷贝构造函数MyClass(const MyClass&) = delete;
};int main() {std::vector<MyClass> vec;vec.emplace_back(1);  // 调用构造函数vec.emplace_back(2);  // 可能扩容时调用移动构造函数
}
2. 没有移动构造函数时

如果没有定义移动构造函数但定义了拷贝构造函数,或者编译器无法隐式生成移动构造函数,则会调用拷贝构造函数。例如:

class MyClass {
public:int* data;MyClass(int value) : data(new int(value)) {}~MyClass() { delete data; }// 拷贝构造函数MyClass(const MyClass& other) : data(new int(*other.data)) {}// 禁用移动构造函数MyClass(MyClass&&) = delete;
};int main() {std::vector<MyClass> vec;vec.emplace_back(1);  // 调用构造函数vec.emplace_back(2);  // 可能扩容时调用拷贝构造函数
}
3. 没有拷贝或移动构造函数

如果既没有拷贝构造函数也没有移动构造函数,并且编译器无法生成隐式的构造函数,编译器会报错。


你的代码分析

对于你的 MyClass

class MyClass {
public:int* data;MyClass(int value) : data(new int(value)) {}~MyClass() { delete data; }// 注意:未显式提供拷贝构造或移动构造
};
  • 如果没有显式定义拷贝和移动构造函数,编译器会隐式生成一个 拷贝构造函数 和一个 移动构造函数,扩容时优先调用隐式移动构造函数。
  • 但是,由于没有显式处理 data 的动态内存管理(例如,深拷贝或移动语义),可能会导致 重复释放内存 的问题,从而引发崩溃。

结论

  1. emplace_back(i) 时,不会调用拷贝构造或移动构造,而是直接调用匹配的构造函数。
  2. 在扩容时:
    • 如果 MyClass 支持移动构造函数,调用移动构造函数。
    • 如果不支持移动构造函数,但支持拷贝构造函数,调用拷贝构造函数。
    • 如果两者都不支持,则报错。
  3. 为了安全,建议显式定义拷贝构造和移动构造函数,并正确管理动态内存。

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

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

相关文章

Unity清除所有的PlayerPrefs

方法1&#xff1a; 直接在你的代码中加入这句 PlayerPrefs.DeleteAll(); 方法2&#xff1a; 点击编辑窗口的这里

非交换几何与黎曼ζ函数:数学中的一场革命性对话

非交换几何与黎曼ζ函数&#xff1a;数学中的一场革命性对话 非交换几何&#xff08;Noncommutative Geometry, NCG&#xff09;是数学的一个分支领域&#xff0c;它将经典的几何概念扩展到非交换代数的框架中。非交换代数是一种结合代数&#xff0c;其中乘积不是交换性的&…

微信小程序下拉刷新与上拉触底的全面教程

微信小程序下拉刷新与上拉触底的全面教程 引言 在微信小程序的开发中,用户体验至关重要。下拉刷新和上拉触底是提高用户交互体验的重要功能,能够让用户轻松获取最新数据和内容。本文将详细介绍这两个功能的实现方式,结合实际案例、代码示例和图片展示,帮助开发者轻松掌握…

数据库的联合查询

数据库的联合查询 简介为什么要使⽤联合查询多表联合查询时MYSQL内部是如何进⾏计算的构造练习案例数据案例&#xff1a;⼀个完整的联合查询的过程 内连接语法⽰例 外连接语法 ⽰例⾃连接应⽤场景示例表连接练习 ⼦查询语法单⾏⼦查询多⾏⼦查询多列⼦查询在from⼦句中使⽤⼦查…

论文阅读:A fast, scalable and versatile tool for analysis of single-cell omics data

Zhang, K., Zemke, N.R., Armand, E.J. et al. A fast, scalable and versatile tool for analysis of single-cell omics data. Nat Methods 21, 217–227 (2024). 论文地址&#xff1a;https://doi.org/10.1038/s41592-023-02139-9 代码地址&#xff1a;https://github.com…

Hive离线数仓结构分析

Hive离线数仓结构 首先&#xff0c;在数据源部分&#xff0c;包括源业务库、用户日志、爬虫数据和系统日志&#xff0c;这些都是数据的源头。这些数据通过Sqoop、DataX或 Flume 工具进行提取和导入操作。这些工具负责将不同来源的数据传输到基于 Hive 的离线数据仓库中。 在离线…

设计模式之 模板方法模式

模板方法模式是行为型设计模式的一种。它定义了一个算法的骨架&#xff0c;并将某些步骤的实现延迟到子类中。模板方法模式允许子类在不改变算法结构的情况下重新定义算法的某些特定步骤。 模板方法模式的核心在于&#xff1a; 封装算法的骨架&#xff1a;通过父类中的模板方…

【分治】--- 快速选择算法

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; 算法Journey &#x1f3e0; 颜色划分 &#x1f4cc; 题目解析 颜色分类 本题要求我们原地对元数组划分0,1,2三个区域,也就是不能使用辅助数组&#xf…

万物皆可Docker,在NAS上一键部署最新苹果MacOS 15系统

万物皆可Docker&#xff0c;在NAS上一键部署最新苹果MacOS 15系统 哈喽小伙伴们还&#xff0c;我是Stark-C~ 最近苹果Mac mini 2024款在政府补贴的加持下&#xff0c;仅需3500块钱左右就能到手确实挺香的。我看很多评论区的小伙伴跃跃欲试&#xff0c;但是也有不少之前从未体…

C++设计模式行为模式———状态模式

文章目录 一、引言二、状态模式三、总结三、总结 一、引言 状态模式是一种行为设计模式&#xff0c; 让你能在一个对象的内部状态变化时改变其行为&#xff0c; 使其看上去就像改变了自身所属的类一样。其实现可完成类似有限状态机的功能。换句话说&#xff0c;一个对象可以处…

vscode自动打印日志插件

自动日志工具&#xff08;Auto Logger Log&#xff09; 概述 自动日志工具&#xff08;Auto Logger Log&#xff09; 是一款 VS Code 扩展&#xff0c;用于简化生成调试日志的过程。它可以为选中的变量自动生成打印语句&#xff0c;帮助开发者快速记录和调试代码。该扩展支持多…

优雅的不等式——Hard

上一文《Easy》末尾出现了又要我们证明的例子&#xff0c;Hard难度就是继续答题答下去 其实一样可以用那篇文章https://zhuanlan.zhihu.com/p/669285539中的式子继续算下去&#xff0c;但是有三个系数&#xff0c;实在是太费时间和人力了 翻到下面的第十九种类型&#xff0c;可…

虚拟局域网PPTP配置与验证(二)

虚拟局域网PPTP配置与验证(二) windows VPN客户端linux 客户端openwrt客户端性能验证虚拟局域网PPTP配置与验证(一)虚拟局域网PPTP配置与验证(二) : 本文介绍几种客户端连接PPTP服务端的方法,同时对linux/windows/openwrt 操作系统及x86、arm硬件平台下PPTP包转发性能进…

Move 合约部署踩坑笔记:如何解决 Sui 客户端发布错误Committing lock file

Move 共学活动&#xff1a;快速上手 Move 开发 为了帮助更多开发者快速了解和掌握 Move 编程语言&#xff0c;Move 共学活动由 HOH 社区、HackQuest、OpenBuild、KeyMap 联合发起。该活动旨在为新手小白提供一个良好的学习平台&#xff0c;带领大家一步步熟悉 Move 语言&#…

介绍一下strupr(arr);(c基础)

hi , I am 36 适合对象c语言初学者 strupr(arr)&#xff1b;函数是把arr数组变为大写字母 格式 #include<string.h> strupr(arr); 返回值为arr 链接分享一下arr的意义(c基础)(必看)(牢记)-CSDN博客 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #incl…

进程间通信5:信号

引入 我们之前学习了信号量&#xff0c;信号量和信号可不是一个东西&#xff0c;不能混淆。 信号是什么以及一些基础概念 信号是一种让进程给其他进程发送异步消息的方式 信号是随时产生的&#xff0c;无法预测信号可以临时保存下来&#xff0c;之后再处理信号是异步发送的…

浅谈网络 | 传输层之套接字Socket

目录 基于 TCP 协议的 Socket 程序调用过程基于 UDP 协议的 Socket 程序函数调用过程服务器如何接入更多的项目构建高并发服务端&#xff1a;从多进程到 IO 多路复用 在前面&#xff0c;我们已经介绍了 TCP 和 UDP 协议&#xff0c;但还没有实践过。接下来这一节&#xff0c;我…

Spire.PDF for .NET【页面设置】演示:打开 PDF 时自动显示书签或缩略图

用户打开 PDF 文档时&#xff0c;他们会看到 PDF 的初始视图。默认情况下&#xff0c;打开 PDF 时不会显示书签面板或缩略图面板。在本文中&#xff0c;我们将演示如何设置文档属性&#xff0c;以便每次启动文件时都会打开书签面板或缩略图面板。 Spire.PDF for .NET 是一款独…

FileLink内外网文件共享系统与FTP对比:高效、安全的文件传输新选择

随着信息技术的不断进步&#xff0c;文件传输和共享已经成为企业日常工作中不可或缺的一部分。传统的FTP&#xff08;File Transfer Protocol&#xff09;协议在一定程度上为文件共享提供了便利&#xff0c;但随着企业对文件传输的需求越来越复杂&#xff0c;FileLink内外网文件…

神经网络归一化方法总结

在深度学习中&#xff0c;归一化 是提高训练效率和稳定性的关键技术。以下是几种常见的神经网络归一化方法的总结&#xff0c;包括其核心思想、适用场景及优缺点。 四种归一化 特性Batch NormalizationGroup NormalizationLayer NormalizationInstance Normalization计算维度…