
2010年6月17日
一个很简单的例子:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v;
int* second;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
second = &v[1];
cout << *second << endl;
for (int i = 0; i < 100; i++) {
v.push_back(i);
}
cout << *second << endl;
return 0;
}
输出结果可想而知。前者为1,后者无效。
STL中说过,当vector在添加新元素时,如果空间已经不足以保存新元素,则开辟一块新的空间,并把之前内容复制到新的空间中去。所以second所指向的元素内存地址已经改变,second变成了一个无效指针。
如果用引用:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
int& second = v[1];
cout << second << endl;
for (int i = 0; i < 100; i++) {
v.push_back(i);
}
cout << second << endl;
return 0;
}
效果相同,事实上很多编译器的引用就是用指针实现的。
这种应用其实非常之多,比如在表达一个Graph:
1 #include <iostream>
2 #include <vector>
3 using namespace std;
4
5
6 class vertex;
7 class edge;
8 class graph;
9
10 class vertex
11 {
12 public:
13 double _x, _y, _z;
14 };
15
16 class edge
17 {
18 //edge中保存两个对应顶点的地址
19 public:
20 vertex* v0;
21 vertex* v1;
22 };
23
24 class graph
25 {
26 //一些初始化函数
27 graph();
28 graph(vertex v[], int nbv, edge e[], int nbe);
29
30 //假设某个函数会插入一组顶点
31 void insert_v(vertex v[], int nbv)
32 {
33 for (int i = 0; i < nbv; i++) {
34 _v_set.push_back(v[i]);
35 }
36 }
37
38
39 //假设用vector来保存edge & vertex
40 public:
41 vector<vertex> _v_set;
42 vector<edge> _e_set;
43 };
44
当调用insert_v时,如果_v_set空间不足进行了拷贝, 则之前所有edge关联顶点的指针全部失效。这就是一场灾难。当调用insert_v时,如果_v_set空间不足进行了拷贝, 则之前所有edge关联顶点的指针全部失效。这就是一场灾难。
一种更好的方式来保存索引号,即:
class edge
{
//edge中保存两个对应顶点的索引
public:
int _v0_handle;
int _v1_handle;
};
posted @
2010-06-17 17:22 tuoxieman 阅读(775) |
评论 (0) |
编辑 收藏