不要轻易定义指向std::vector中的元素的指针
类应该是被封装的,类的用户通过接口使用类提供的功能,而不必关心类的内部如何实现。然而,C++标准库容器 std::vector 的实现渗透到了接口中来。对于以下代码:
const int pushNum = 10;
std::vector<int> v = { 1,2,3 };
int* p = &v[1];
std::cout << "*p = " << * p << std::endl;
std::cout << "v[1] = " << v[1] << std::endl;
for (int i = 0; i < pushNum; i++)
v.push_back(i);
std::cout << "---------------------" << std::endl;
std::cout << "*p = " << *p << std::endl;
std::cout << "v[1] = " << v[1] << std::endl;
我们初始化了一个有3个int元素的vector,定义了一个int 指针p,指向v[1] , 打印 *p 以及v[1] 的值。 然后向 v 中push_back() 了10 个元素,之后再次打印 *p 以及 v[1] 的值。在作者的环境中,程序的运行结果如下:

可以看到,在最初的v 中,打印出的*p 以及 v[1] 的值都是2, 这正是容器中下标为 1 的元素的值。 而push_back() 一些元素之后,v[1] 仍然是2,但是*p 的值却变了。指针p指向的就是v[1] ,为什么会这样呢?原因要追溯到标准库std::vector的实现。
std::vector 对象动态管理内存空间,一个std::vector 对象所分配的所有内存空间未必都构造了元素。可以使用其成员函数size() 返回其已构造的元素数量, 使用capacity() 返回其已分配的总容量,即,已分配的内存一共可以构造多少个元素。随着我们不断push_back(),size 会逐渐增加,直到capacity没有足够的空间能够容下下一个元素,这时,std::vector就会分配更多的内存。然而,std::vector 要求元素是连续存储的,如果此时连续的内存已经没有更多的空间了,std::vector会把所有元素搬到一块其他的,更大的内存空间,来容纳更多元素,并且其内部实现会保证其重载的下标访问运算符 [ ] 是有效的,然而std::vector 无法得知此时有一个指针p指向了容器内的元素,所以无法更新指针,而指针所指向的旧的内存现在是未知的。
那么std::vector 每次重新分配的时候会申请多大的空间作为capacity() ? 作者在自己的环境中做了一些实验,但并没有发现什么规律。
不要轻易定义指向std::vector中的元素的指针的更多相关文章
- vector中的元素删除
删除vector中的元素,最容易的方法就是使用vector的erase()函数. vector vec;for ( vector::iterator iter = vec.begin(); iter! ...
- std::set 中内部元素有序条件删除的理解
std::set 中内部元素有序条件删除的理解 1. std::set中的元素是有序排列的 注意:Set集合中的元素通过iterator的引用,但是不能修改. 元素排序: (1)元素中实现比较oper ...
- 关于Vector中的元素中含有指针成员的情况
对于容器,当容器的各个元素为类类型,且该类类型中含有指针成员时: 如果类类型的析构函数中包含了对指针变量指向内存的释放操作,则在利用clear()函数删除容器所有元素时,会自动调用类的析构函数,自动实 ...
- (c++ std) 查找 vector 中的元素
You can use std::find from <algorithm>: std::find(vector.begin(), vector.end(), item) != vecto ...
- 元素为指针的vector的使用说明
该程序演示了vector中的元素为指针的时候的对对象的操作. /* 功能说明: 元素为指针的vector的使用说明 实现方式: 使用this成员来显示各个对象的地址. 限制条件或者存在的问题: 无 * ...
- C++之vector中元素删除
今天在删除vector中的元素中遇到一个问题,这里记录下来以便以后查阅. 预备知识:用到了erase()函数,对于一个容器c来说,假设迭代器为p,那么执行: c.erase(p)之后就删除了容器c中p ...
- 【转】java.util.vector中的vector的详细用法
[转]java.util.vector中的vector的详细用法 ArrayList会比Vector快,他是非同步的,如果设计涉及到多线程,还是用Vector比较好一些 import java.uti ...
- java.util.vector中的vector的详细用法
ArrayList会比Vector快,他是非同步的,如果设计涉及到多线程,还是用Vector比较好一些 import java.util.*; /** * 演示Vector的使用.包括Vector的创 ...
- C++ std::vector 基本用法2
#include <iostream> #include <vector> using namespace std; int main() { int ar[10] = { 1 ...
- 查漏补缺:Vector中去重
对于STL去重,可以使用<algorithm>中提供的unique()函数. unique()函数用于去除相邻元素中的重复元素(所以去重前需要对vector进行排序),只留下一个.返回去重 ...
随机推荐
- OpenLayers示例
http://develop.smaryun.com:81/API/JS/OL3InterfaceDemo/index.htm
- 【go笔记】从安装到helloworld
前言 Go语言也称Golang,google出品,特点在于编程简便的同时并发性能不俗. 环境准备: Go语言版本:1.17.2.安装包下载链接:https://studygolang.com/dl l ...
- CSS实现文字描边效果
一.介绍最近在一个项目的宣传页中,设计师使用了文字描边效果,之前我确实没有实现过文字的描边效果,然后我在查阅资料后,知道了实现方法.文字描边分为两种:内外双描边和单外描边,也就是指在给文字加上描边效果 ...
- ORM分组查询复杂查询
记录一下自己在工作中遇到的一个问题,就是根据一个字段分类,然后还要统计这个字段不同状态的数量,这里我举个例子 假如有好多学生,这些学生来自不同的班级,现在我们要统计每一个班级中男生和女生的数量 def ...
- Go 语言内置类型全解析:从布尔到字符串的全维度探究
关注微信公众号[TechLeadCloud],分享互联网架构.云服务技术的全维度知识.作者拥有10+年互联网服务架构.AI产品研发经验.团队管理经验,同济本复旦硕,复旦机器人智能实验室成员,阿里云认证 ...
- glog 日志库简介与测试【GO 常用的库】
〇.前言 golang/glog 是 C++ 版本 google/glog 的 Go 版本实现,基本实现了原生 glog 的日志格式. 在 Kuberntes 中,glog 是默认日志库.因此需要详细 ...
- web应用及微信小程序版本更新检测方案实践
背景: 随着项目体量越来越大,用户群体越来越多,用户的声音也越来越明显:关于应用发版之后用户无感知,导致用户用的是仍然还是老版本功能,除非用户手动刷新,否则体验不到最新的功能:这样的体验非常不好,于是 ...
- 13.1 使用DirectX9绘图引擎
DirectX 9 是由微软开发的一组多媒体应用程序接口API,用于创建和运行基于Windows平台的多媒体应用程序,尤其是游戏.它是DirectX系列中的一个版本,于2002年发布,是DirectX ...
- Meteors 题解
Meteors 蒟蒻初学整体二分,写一篇题解记录一下思考与看法. 题目大意 在一个环形的轨道上分别着若干国家的空间站,在接下来的一段时间内会出现若干次陨石,每次出现在环形的某一段轨道,每个国家都想收集 ...
- 深入理解 Netty FastThreadLocal
作者:vivo 互联网服务器团队- Jiang Zhu 本文以线上诡异问题为切入点,通过对比JDK ThreadLocal和Netty FastThreadLocal实现逻辑以及优缺点,并深入解读源码 ...