C++ vector,dequeu,list容器中元素的引用失效问题

文章目录

  • 一、std::list不会产生引用失效问题
  • 二、std::vector中元素引用失效问题
  • 三、std::deque中元素引用失效问题

一、std::list不会产生引用失效问题

在C++中,std::list(双向链表)提供了一种非常灵活的容器类型,其设计使其在插入和删除元素时不会使其他元素的引用或指针失效。这是因为std::list在内部使用节点来存储元素,每个节点都包含指向前后节点的指针,因此插入和删除操作只会影响相邻节点的指针,而不会影响其他节点。

std::list的引用和指针有效性:

  • 插入元素:插入元素时,只需要调整相邻节点的指针,而不会重新分配或移动其他节点。因此,现有元素的引用和指针不会失效。
  • 删除元素:删除元素时,只需要调整相邻节点的指针,然后删除节点本身。其他节点的引用和指针仍然有效。

eg:在std::list中插入和删除元素后,现有元素的引用和指针仍然有效:

#include <iostream>
#include <list>int main() {std::list<int> myList = {1, 2, 3, 4};// 获取指向第二个元素的引用和指针auto it = myList.begin();++it; // it指向第二个元素(2)int& ref = *it;std::cout << "Value of ref before insertions: " << ref << std::endl; // 输出2// 在列表中插入和删除元素myList.insert(it, 10); // 在第二个元素之前插入10myList.push_back(5);   // 在末尾插入5std::cout << "Value of ref after insertions: " << ref << std::endl; // 输出2myList.erase(it); // 删除第二个元素(2)std::cout << "List after deletions: ";for (const auto& value : myList) {std::cout << value << " ";}std::cout << std::endl;return 0;
}

测试:

Program returned: 0
Program stdout
Value of ref before insertions: 2
Value of ref after insertions: 2
List after deletions: 1 10 3 4 5 

在这个示例中,即使在列表中插入和删除元素后,ref(原本指向第二个元素的引用)仍然有效,并且保持其值为2。

使用智能指针避免同样会导致引用失效问题

  • 使用智能指针(如std::shared_ptr和std::unique_ptr)可以显著减少引用失效问题,因为智能指针管理的是指向堆上对象的指针,而不是对象本身。
#include <iostream>
#include <memory>
#include <vector>int main() {std::vector<std::shared_ptr<int>> vec = {std::make_shared<int>(1),std::make_shared<int>(2),std::make_shared<int>(3)};std::shared_ptr<int>& ref = vec[1];  // 引用第二个元素std::cout << *ref << std::endl;      // ref仍然有效,输出2vec.insert(vec.begin(), std::make_shared<int>(0));  // 在开头插入一个元素std::cout << *ref << std::endl;  return 0;
}

编译:

Program returned: 139
Program stdout
2
Program stderr
Program terminated with signal: SIGSEGV

二、std::vector中元素引用失效问题

std::vector在以下情况下可能导致引用失效:

  • 重新分配内存:当vector的容量不够时,会重新分配内存,将现有元素移动到新的内存位置。
  • 插入和删除:在中间插入或删除元素时,后续元素会被移动,从而使指向这些元素的引用失效。

避免引用失效的方法:

  • 预先分配足够的空间:使用reserve方法预先分配足够的空间,以减少重新分配内存的次数。
std::vector<int> vec;
vec.reserve(100); // 预先分配足够的空间
  • 避免中间插入和删除:尽量减少在中间插入和删除元素的操作,可以选择在尾部插入或删除。

三、std::deque中元素引用失效问题

std::deque的设计使其在头尾插入和删除操作中引用失效的可能性较低,但在中间插入和删除时仍然可能导致引用失效。

避免引用失效的方法:

  • 避免中间插入和删除:和vector类似,尽量减少在中间插入和删除元素的操作。
  • 使用迭代器:在插入或删除元素后,重新获取迭代器。

使用智能指针避免同样会导致引用失效问题

  • 在队列中间插入新的元素之后,旧的元素的值不正确
#include <deque>
#include <iostream>
#include <memory>
#include <vector>int main() {std::deque<std::shared_ptr<int>> deq = {std::make_shared<int>(1),std::make_shared<int>(2),std::make_shared<int>(3)};std::shared_ptr<int>& ref = deq[1];  // 引用第二个元素std::cout << *ref << std::endl;      // ref仍然有效,输出2deq.insert(deq.begin() + 1,std::make_shared<int>(10));  // 在第二个位置插入元素std::cout << *ref << std::endl;  // ref仍然有效,   但是输出10return 0;
}

编译:

Program returned: 0
Program stdout
2
10

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

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

相关文章

微信小程序的事件对象属性,事件绑定

微信小程序 小程序简介 1 小程序与普通网页开发的区别&#xff1f; 1运行环境的不同&#xff1a;网页运行在浏览器&#xff0c;小程序运行在微信环境&#xff1b; 2.API 不同&#xff1a;小程序无法调用 DOM 和 BOM 的 API&#xff0c;但可以调用微信环境提供的 API&#xff1…

单工无线发射接收系统

1 绪论 随着无线电技术的发展,通讯方式也从传统的有线通讯逐渐转向无线通讯。由于传统的有线传输系统有配线的问题,较不便利,而无线通讯具有成本廉价、建设工程周期短、适应性好、扩展性好、设备维护容易实现等特点,故未来通讯方式将向无线传输系统方向发展。同时,实现系…

mfc140.dll丢失原因和mfc140.dll丢失修复办法分享

mfc140.dll是与微软基础类库&#xff08;Microsoft Foundation Classes, MFC&#xff09;紧密相关的动态链接库&#xff08;DLL&#xff09;文件。MFC是微软为C开发者设计的一个应用程序框架&#xff0c;用于简化Windows应用程序的开发工作。以下是mfc140.dll文件的一些关键属性…

栈的实现(C语言)

文章目录 前言1.栈的概念及结构2.栈的实现3.具体操作3.1.初始化栈(StackInit)和销毁栈(StackDestory)3.2.入栈(StackPush)和出栈(StackPop)3.3.获得栈的个数(StackSize)、获得栈顶元素(StackTop)以及判空(StackEmpty) 前言 前段时间我们学习过了链表和顺序表等相关操作&#x…

go-zero 实战(4)

中间件 在 userapi 项目中引入中间件。go项目中的中间可以处理请求之前和之后的逻辑。 1. 在 userapi/internal目录先创建 middlewares目录&#xff0c;并创建 user.go文件 package middlewaresimport ("github.com/zeromicro/go-zero/core/logx""net/http&q…

经济寒冬下的黄金跳板:方案、活动、竞标一手掌握

推荐策划人必备的宝藏地产策划资源平台&#xff0c; 订阅浩叫&#xff1a;地产营销策划圈。这个平台简直是地产策划人的百宝箱&#xff0c;里面藏着无数的策划秘籍&#xff0c;等着你来挖掘。 这个平台就像是一个大型的方案库&#xff0c;里面收录了众多知名地产企业的内部资料…

leetcode:计数质数

class Solution { public:// 如果 x 是质数&#xff0c;那么大于 x 的 x 的倍数 2x,3x… 一定不是质数int countPrimes(int n) {vector<int> isPrime(n, 1);int ans 0;for (int i 2; i < n; i) {if (isPrime[i]) {ans 1;if ((long long)i * i < n) {for (int j …

leetcode-55 跳跃游戏

leetcode Problem: 55. 跳跃游戏 思路 假设我们是一个小人&#xff0c;从第一个下标开始&#xff0c;每次经过一个位置&#xff0c;我们就可以根据当前位置的数值nums[i]和位置下标i计算出该位置所能到达的后续位置的最大值rnums[i]i。而这个r之前的区域一定都是可以经过的。…

AI 谈“浔川AI翻译机”

在天工AI&#xff0c;天工AI在全网搜索“浔川AI翻译机”。 1 创作助手谈“浔川AI翻译机”&#xff1a; “浔川AI翻译机”是一个利用人工智能技术进行语言翻译的设备或应用程序。它可以将一种语言的文字或口语翻译成另一种语言&#xff0c;以实现不同语言之间的沟通和理解。浔…

08. Redis 缓存穿透和雪崩

文章目录 1. 缓存穿透&#xff08;查不到导致的&#xff09;1.1 概念1.2 解决方案布隆过滤器缓存空对象 2. 缓存击穿&#xff08;量太大、缓存过期&#xff09;2.1 概念2.2 解决方案设置热点数据永不过期加互斥锁 3. 缓存雪崩&#xff08;缓存集体失效或 Redis 宕机&#xff09…

说一下你对dom驱动和数据驱动的理解

DOM驱动和数据驱动是前端开发中两种常见的操作方式&#xff0c;尤其在构建用户界面时。下面&#xff0c;我将分别解释这两种驱动方式&#xff0c;并提供详细的代码示例。 DOM驱动 DOM驱动的核心思想是直接操作DOM元素来更新用户界面。在早期的Web开发中&#xff0c;这种方式非…

Linux指令初识

ls:显示当前目录底下的指定文件或目录 ls -l更详细的信息 ls -a显示当前目录下的所有文件 命令中的选项可以一次传递多个 ,例如&#xff1a;ls -al 命令和选项有必须一个或多个空格 以.开头的文件&#xff0c;为隐藏文件ls -a可以看到,ls -l看不见 支持命令拼在一起&#…

牛客热题:滑动窗口的最大值

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题&#xff1a;滑动窗口的最大值题目链接方法一…

DNS服务的部署与配置(2)

1、dns的安装及开启 dnf install bind.x86_64 -y #安装 #Berkeley Internet Name Domain (BIND) systemctl enable --now named #启用dns服务&#xff0c;服务名称叫named firewall-cmd --permanent --add-servicedns #火墙设置 firewall-cmd --reload …

【手把手搓组件库】从零开始实现Element Plus--组件开发

从零开始实现Element Plus--组件开发 nvmnvm的作用&#xff1a;nvm的使用方法 需求分析提示词Kimi 生成产品需求文档kimi 生成测试用例 初始化 vitest完善 Button 组件1、定义 types.ts2、Button.vue 引入 types.ts3、添加Button样式点击事件 添加节流添加 Icon 集成 StoryBook…

C++第十九弹---string模拟实现(下)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1、修改操作 2、迭代器操作 3、字符串操作 4、非成员函数重载操作 总结 1、修改操作 1、string& operator (const char* s); //尾部插入…

【Text2SQL 论文】SeaD:使用 Schema-aware 去噪训练的 end2end 的 Text2SQL

论文&#xff1a;SeaD: End-to-end Text-to-SQL Generation with Schema-aware Denoising ⭐⭐ NAACL 2022, arXiv:2105.07911 本论文提出 SeaD 模型&#xff0c;使用 schema-aware 的去噪方法来训练一个 end2end、seq2seq 的 Transformer 模型来实现 Text2SQL。 一、论文速读…

C++系列-static成员

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 概念 声明为static的类成员称为类的静态成员&#xff0c;用static修饰的成员变量&#xff0c;称之为静态成员变量&#xff0c;用static修饰的成员函数&#xff0c;称之为静态成…

stm32学习-流水灯

接线 注意&#xff1a;LED灯长一点的引脚是正极。 配置GPIO 1.使用RCC开启GPIO时钟 void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState); void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState); void RCC_APB1Perip…

Stanford斯坦福 CS 224R: 深度强化学习 (2)

实用深度强化学习实现技术 强化学习(RL)是一种通过智能体与环境交互来学习最优决策的机器学习范式。而深度强化学习(DRL)则将深度学习技术引入RL领域,利用深度神经网络强大的函数拟合能力来处理高维观察空间,取得了显著的成功。本章我们将重点介绍一种经典的DRL算法:Q-Learnin…