c++ - 指针在 push_back 后被修改
问题描述
让我们考虑以下 c++ 代码
#include <iostream>
#include <vector>
class A {
int x, y;
public:
A(int x, int y) : x(x), y(y){}
friend std::ostream & operator << (std::ostream & os, const A & a){
os << a.x << " " << a.y;
return os;
}
};
int main(){
std::vector<A> a;
std::vector<const A*> b;
for(int i = 0; i < 5; i++){
a.push_back(A(i, i + 1));
b.push_back(&a[i]);
}
while(!a.empty()){
a.pop_back();
}
for(auto x : b)
std::cout << *x << std::endl;
return 0;
}
使用调试器,我注意到在第一次插入更改a
地址后a[0]
。因此,当我在第二个 for 循环中打印时,我得到了对第一个条目的无效引用。为什么会这样?
谢谢你的帮助!
解决方案
for(int i = 0; i < 5; i++){
a.push_back(A(i, i + 1)); //add a new item to a
b.push_back(&a[i]); // point at the new item in a
}
直接的问题是Iterator invalidation。随着a
增长,它会重新分配其存储以获得更多容量。这可能会使指针b
指向已返回到 freestore(可能是堆)的内存。访问这些指针会调用未定义的行为,任何事情都可能发生。对此有一些解决方案,例如提前保留空间以消除重新分配或使用具有更宽容的失效规则的容器,但无论您做什么,下一个问题都会变得没有意义。
while(!a.empty()){
a.pop_back(); // remove item from `a`
}
由于 in 中的项b
指向 in 中的项,a
并且 in 中没有项,因此现在 ina
中的所有指针b
都引用了无效对象,并且在不调用 Undefined Behaviour 的情况下无法访问。
只要项目 in存在或从和中删除,项目 ina
引用的所有项目都必须保持活动状态。b
b
a
b
在这种微不足道的情况下,答案很简单,不要为空a
,但这违背了示例的要点。对于一般情况有很多解决方案(只使用a
, 存储副本而不是指针 in b
,在两者中使用std::shared_ptr
和存储shared_ptr
s 到A
sa
和b
)但是要提出有用的建议,我们需要知道如何a
以及b
正在被消费。
推荐阅读
- python - 创建一个python数组,其中外部元素按时间顺序增加
- android - WebSQL PhoneGap 没有返回 insertId?
- visual-studio - Redis 缓存显示相同的用户详细信息,不同的用户也登录。我应该如何、何时以及从何处处理连接
- c# - 读取 XML 元素并将它们连接到 1 个变量中
- asp.net-core - Asp.Net Core 2.1 - 根据请求中的内容进行授权
- php - PHP SFTP 上传的文件被自动删除
- uwp - 有没有办法从 UWP 应用程序中的 IVpnProfile 获取 ConnectionStatus?
- gupshup - 错误 | 253 | 指定的消息与任何模板都不匹配
- jquery - 根据屏幕宽度在 div 中切换文本
- sql - 如何为 ParentId/HierarchyId 编写多行约束