C++ vector 访问元素用 at 和 [] 有什么区别?
C++ vector 访问元素用 at and [] 有什么区别?
前言: 最近同事开发过程遇到了一个奇怪的coredump问题,崩溃位置和提交改动没有任何关系,看了几小时后来才发现原来是
vector越界访问了,使用了[]越界访问元素。在此,记录一下at()和[]的区别,便于日后可以更快速地定位问题。
1. 源码对比
- operator[]
/* This operator allows for easy, array-style, data access.
- Note that data access with this operator is unchecked and
- out_of_range lookups are not defined. (For checked lookups
- see at().)
- */
reference
operator[](size_type __n) _GLIBCXX_NOEXCEPT
{
__glibcxx_requires_subscript(__n);
return *(this->_M_impl._M_start + __n);
}
从以上代码以及注释可以看出, []下标运算符不会做越界访问保护,而且不会抛出异常,所以使用[]访问元素时,需要自己做越界检查,否则可能会导致未定义的行为。
- at()
/* This function provides for safer data access. The parameter
- is first checked that it is in the range of the vector. The
- function throws out_of_range if the check fails.
- */
reference
at(size_type __n)
{
_M_range_check(__n);
return (*this)[__n];
}
从源码中可以看到,at()函数会做越界访问保护,如果越界会抛出out_of_range异常,然后再通过operator[]运行访问。
2. 代码测试
- []
以下代码不会抛出异常,但是会导致未定义的行为,程序继续运行,但程序可能在某个时候崩溃,增加了问题定位难度。
std::vector<int> arr;
arr[1]; //
- at()
以下代码会抛出out_of_range异常,在访问元素时立即崩溃。
std::vector<int> arr;
arr.at(1);
3. 如何快速定位内存错误?
ASAN(gcc address sanitizer)是一个内存错误检测工具,可以检测内存越界访问,内存泄漏等问题。
例如以下程序:
int func() {
std::vector<int> arr;
return arr[1];
}
std::cout<<func()<<std::endl;
通过以下命令编译程序,然后运行程序:
g++ -g -fsanitize=address -fno-omit-frame-pointer -o vector_test vector_test.cpp
./vector_test
当程序发生内存错误时,会打印出错误信息:
AddressSanitizer:DEADLYSIGNAL
=================================================================
==2026418==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000004 (pc 0x5615f166641e bp 0x7ffde401e7d0 sp 0x7ffde401e720 T0)
==2026418==The signal is caused by a READ memory access.
==2026418==Hint: address points to the zero page.
#0 0x5615f166641d in func() /home/qiang/CppTest/vector_test.cpp:7
#1 0x5615f16664af in main /home/qiang/CppTest/vector_test.cpp:12
#2 0x7fa0b1af7082 in __libc_start_main ../csu/libc-start.c:308
#3 0x5615f166626d in _start (/home/qiang/CppTest/vector_test+0x126d)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/qiang/CppTest/vector_test.cpp:7 in func()
==2026418==ABORTING
4. 结论
- 当对效率要求较高时,使用
[]访问元素,但是需要自己做越界检查。 - 当对效率要求不高时,使用
at()访问元素,会做越界检查,如果越界会抛出out_of_range异常。
5. 启示
当发生奇怪的coredump时,可以尝试使用ASAN等工具检测内存错误,可以快速定位问题。
你好,我是七昂,致力于分享C++、操作系统、软件架构、机器学习、效率提升等系列文章。希望我们能一起探索程序员修炼之道,高效学习、高效工作。如果我的创作内容对您有帮助,请点赞关注。如果有问题,欢迎随时与我交流。感谢你的阅读。
{{uploading-image-322250.png(uploading...)}}
C++ vector 访问元素用 at 和 [] 有什么区别?的更多相关文章
- DOM访问元素样式和操作元素样式
在HTML中定义样式的方式有三种:通过<link/>元素包含外部样式表文件(外部样式表).使用<style/>元素定义嵌入式样式(嵌入式样式表).使用style特性定义针对特定 ...
- 【JavaScript】frame跨域访问元素
什么是跨frame访问元素呢?比如main.html中有如下代码: <frameset cols="50%,*"> <frame src="frame1 ...
- PAT 甲级 1053 Path of Equal Weight (30 分)(dfs,vector内元素排序,有一小坑点)
1053 Path of Equal Weight (30 分) Given a non-empty tree with root R, and with weight Wi assigne ...
- auto_ptr为什么不能做为vector的元素
昨天看effectve c++的时候,发现了auto_ptr这个东西.由于我待过的公司都是用的老版c++,代码里智能指针什么的完全没有出现过,都是直接操作的原始指针.虽说我很少出错,但是总归还是不太安 ...
- 【C++】Vector判断元素是否存在,去重,求交集,求并集
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> //sort函数.交并补函数 4 ...
- 【转】STL中vector、list、deque和map的区别
1.vector 向量 相当于一个数组 在内存中分配一块连续的内容空间进行存储.支持不指定vector大小的存储.STL内部实现时,首先分配一个非常大的内存空间预备进行存储,即capacity()函数 ...
- Java容器类List、ArrayList、Vector及map、HashTable、HashMap的区别与用法
Java容器类List.ArrayList.Vector及map.HashTable.HashMap的区别与用法 ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数 ...
- 元素(Element)和结点(Node)的区别(org.w3c.dom)
1.元素(Element)和结点(Node)的区别, 元素是一个小范围的定义,必须是含有完整信息的结点才是一个元素,例如 - . 但是一个结点不一定是一个元素,而一个元素一定是一个结点. 什么是nod ...
- html元素中id和name的区别
可以说几乎每个做过Web开发的人都问过,到底元素的ID和Name有什么区别阿?为什么有了ID还要有Name呢?! 而同样我们也可以得到最classical的答案:ID就像是一个人的身份证号码,而Nam ...
- jQuery获得元素位置offset()和position()的区别
jQuery获得元素位置offset()和position()的区别 jQuery 中有两个获取元素位置的方法offset()和position(),这两个方法之间有什么异同 offset(): 获取 ...
随机推荐
- 10分钟快速掌握分布式版本控制系统GIT命令集【形成知识体系篇】
任务要求 要求全部使用git命令实现 1.创建本地仓库,项目名称为hniu_site 2.在仓库下创建多级(目录)文件夹cn/hniu/班级名称(例如软件2108,cn/hniu/rj2108) 3. ...
- PHP转Go系列 | ThinkPHP与Gin框架之OpenApi授权设计实践
大家好,我是码农先森. 我之前待过一个做 ToB 业务的公司,主要是研发以会员为中心的 SaaS 平台,其中涉及的子系统有会员系统.积分系统.营销系统等.在这个 SaaS 平台中有一个重要的角色「租户 ...
- [oeasy]python0031_挂起进程_恢复进程_进程切换
查看进程 回忆上次内容 上次修改了 $PATH 路径 把当前用户shiyanlou的宿主文件夹 ~ 添加到 $PATH 中 这样 sleep.py 就可以被找到 于是就可以被执行了 还可以把配置 ...
- Jmeter函数助手34-digest
digest函数用于返回特定哈希算法的加密值. 算法摘要:填入算法,如MD2.MD5.SHA-1.SHA-224.SHA-256.SHA-384.SHA-512 String to be hashed ...
- 对比python学julia(第四章:人工智能)--(第三节)目标检测
1.1. 项目简介 目标检测(Object Detection)的任务是在图像中找出检测对象的位置和犬小,是计算机视觉领域的核心问题之一,在自动驾驶.机器人和无人机等许多领域极具研究价值. 随着深度 ...
- 【Mybatis】06 Session获取 & 配置参数总结
会话获取 SqlSessionFactory 最佳的获取方式就是使用Mybatis提供的资源类加载配置文件 调用会话工厂建造者实例的建造方法注入读取流 要注意的是建造者生成了了实例就可以不需要了 这里 ...
- 【Windows】解决微软商店打不开的问题
参考贴吧的帖子: https://tieba.baidu.com/p/6028738660#123983609458l 1.打开"运行"输入 inetcpl.cpl (" ...
- 【SpringBoot】03 自动装配原理探索
SpringBoot的依赖探索 首先是一个父级依赖管理的pom.xml [Ctrl + 左键点击]访问进去之后还有父级的父级 到最后才是我们的真正的顶级父类Pom.xml 我们当前的父级坐标 < ...
- 数值优化算法-BFGS
参考: https://www.cnblogs.com/Leo_wl/p/3367323.html 牛顿法: 使用牛顿法优化函数 f(θ) 最小值时,每次计算获得新的\(θ\)值,即\(θ_{k+1} ...
- 大连人工智能计算平台——华为昇腾AI平台——高性能计算HPC——如何在MPI中支持multiprocessing和fork操作——如何在HPC平台上使用pytorch——是否可以通过调度器的提交参数绕过HPC的计费系统
本文要讨论的就是如何在MPI中支持multiprocessing和fork操作,但是这个问题同时也是如何在HPC平台如何使用pytorch的问题,可以说这两个问题其实是同一个问题,而这个问题的解决过程 ...