不要轻易定义指向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进行排序),只留下一个.返回去重 ...
随机推荐
- 为什么大于 $3$ 的素数可以表示为 $6n\pm1$?
我们有一个素数 \(p\),都能表示为 \(6n \pm 1\). 为什么呢? 我们设 \(p = 6n \pm k\),\(k\) 可以是 \(0, 1, 2, 3, 4, 5\). 如果 \(k\ ...
- 一款开源免费、更符合现代用户需求的论坛系统:vanilla
对于个人建站来说,WordPress相信很多读者都知道了.但WordPress很多时候我们还是用来建立自主发布内容的站点为主,适用于个人博客.企业主站等.虽然有的主题可以把WordPress变为论坛, ...
- 使用logrotate定期切割nginx日志
前言 默认情况下,nginx的日志都会写到access.log文件中,访问流量大的话,日志文件很快就会膨胀到几十G,不方便分析处理,也占用硬盘空间.借助linux自带的logrotate工具可以很方便 ...
- 重学HTTP:理解同源策略和CORS
每次遇到跨域.代理.CORS这几个词都懵懵的,我决定一次把他们都搞明白,以后遇到他们再也不用害怕了. 一.什么是同源策略? 同源策略是在1995年由 Netscape公司引入到浏览器的,目前所有浏览 ...
- 监控keepalived_vip控制容器的状态
需求:监控server服务器的vip状态,如果vip存在,则判断容器是否启动,如果没有启动,则启动容器.如果vip不存在则关闭容器. 方法一: 查看代码 #!/bin/bash ip add | gr ...
- CutLER:一种用于无监督目标检测和实例分割的方法
本文分享自华为云社区<CutLER:一种用于无监督目标检测和实例分割的方法>,作者:Hint. 目标检测是计算机视觉中的一种重要任务,使AI系统感知.推理.理解目标.训练定位模型需要特别的 ...
- api接口对接如何实现,php如何对接api
API接口对接是现代软件开发中不可或缺的一部分,它允许不同的应用程序之间进行数据交换和服务调用.在PHP中,可以使用多种方式实现API接口的对接,包括基于HTTP协议的传统方法以及现代的API客户端库 ...
- Python图片与Base64相互转换
import base64 #必须的 pic=open("img.png","rb")#读取本地文件 pic_base=base64.b64encode(pic ...
- 当你使用Taro时,你需要了解的一些事儿
2017 年 1 月 9 日凌晨,万众期待的微信小程序正式上线,前有跳一跳等爆圈小游戏的带动,后有特殊时期下各类健康码小程序的加持,小程序成为了国内技术圈独树一帜的存在.但随着小程序的迅猛发展,其实在 ...
- 领域驱动模型DDD(四)——Eventuate Tram Saga源码讲解
前言 虽然本人一直抱怨<微服务架构设计模式>中DDD模式下采用的Eventuate Tram Saga不算简单易用,但是为了更加深入了解原文作者的设计思路,还是花了点时间去阅读源码,并且为 ...