我们在用动态内存分配时,经常是用new来定义一块内存空间,比如说 int* p = new int(1);这时会在堆上分配一块内存,当作int类型使用,内存中存储的值为1并将内存地址赋值给在栈中的int*类型的p,此时p本身也有一个内存地址,p的内容是一块地址,该地址指向1,相当于p与1关联。
当不使用p时,往往需要用delete p将其释放,我们需要注意的是释放一个指针p(delete p;)编译器只会释放该指针所指向的内存空间,而不会删除这个指针本身。实际意思是断开p与1的关联,释放了它所占的堆空间,而不是删除p本身(指针p本身并没有撤销,它自己仍然存在,该指针所占内存空间并未释放,指针p的真正释放是随着函数调用的结束而消失),释放堆空间后,p成了"野指针",*p成为了随机数,所以为了安全一般会在释放后置空(p=NULL)。
example:
vector<int*> pInt;
for (int i = 0; i < 10; i++)
{
int *a = new int;
*a = i;
pInt.push_back(a);
}
vector.push_back是将地址放入,当然这样说也有些问题,应当是拷贝一份地址
同样的下面这样写也是错误的
for (int i = 0; i < 10; i++)
{
pInt.push_back(&i);
}
不能这么操作,因为 i 在这个循环中只有一个地址,那么push进去的所有值都指向这同一个地址,修改一个就会全部都一起变
vector<int*> pInt;
for (int i = 0; i < 10; i++)
{
int *a = new int;
*a = i;
pInt.push_back(a);
delete a;
}
这里不能 delete a; 因为delete删除的是a指向的地址上的变量,选择pInt的每个元素都指向了他们,删除了也将没了,只会变成随机数,就是所谓的悬空指针。
vector<int*> pInt;
for (int i = 0; i < 10; i++)
{
int a;
a = i;
pInt.push_back(&a);
}
这样做也是不行,这样的话跟直接把 i 给 pInt 中 push 进去是没有区别的,a在定义时候初始化为 i 也是一样的。但是为什么会这样呢?输出了一些信息之后发现,此时 a 和 i 的地址是不一样的,但是!a 每次的地址都是一样的,所以第二次循环定义一个 a 对他进行赋值操作时候先前push进去的 a 的也是会一起变得,因为是同一个地址。
所以现阶段我自己能想到的最好的办法是自己分配内存,然后用完了以后如果需要释放内存就先释放内存,然后让指针指向NULL,如果不需要,那块地址已经有别人接管了,那就让之前那个指针直接指向NULL就可以了。如下:
vector<int*> pInt;
for (int i = 0; i < 10; i++)
{
int *a = new int;
*a = i;
pInt.push_back(a);
a = NULL;
}
通过这个例子还能看出一个事情,就是,vector他push_back时候并不是将a拿过来插进去了,而是新开辟了一个内存,把a的值赋给新开辟的内存,也就是pInt[0]。(毕竟vector它说白了是数组,并不是链表,所以他的内存地址是连续的,不可能把一个随随便便的a加进来,链表的话还能理解)
总结:vector的push有两种情况,若源数据在栈上创建,则拷贝值,若源数据在堆上创建,则拷贝其指向的地址