欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于存储指针变量的vector的若干问题

程序员文章站 2022-04-16 21:17:27
...

前言

很多初学者认为学习C++很难的一个重要原因就是关于内存管理的问题,因为它不像Java等一些高级编程语言提供了垃圾自动回收的机制(你只管使用,剩下的交给OS);在C++中,如果你手动申请了一段内存空间,那么一定要记得在用完之后手动释放(你既要管申请,又要管释放),否则会造成内存泄漏等问题。这是一个让人又爱又恨的特性,你可以随意申请空间,但是又要小心翼翼地使用。那么说到内存管理,不得不涉及到C++中一个重要的角色——指针,指针的合理使用本身就是一个很难的问题,如果和vector等一些容器结合起来使用,出现的问题会更多,这里我列举几个在项目中遇到的问题,为了简化问题,以内置类型代替了复杂的类类型,目的只是为了还原一个场景。

一、插入后再delete

将一个指针变量插入vector之后,再手动delete,那么vector中的元素所指向的内存空间同样会失效,请看下面代码。

#include <iostream>
#include <vector>
using namespace std;

vector<int*> _data;
void Function()
{
	for (int i = 0; i < 10; ++i)
	{
		int* temp1 = new int(i + 1);
		_data.push_back(temp1);
		delete temp1;
		temp1 = nullptr; // 指针在delete之后一定要设为空,否则变成dangling pointer悬挂指针
	}
}

int main()
{
	Function();
	for (int i = 0; i < _data.size(); ++i)
		cout << *_data[i] << endl;
	system("pause");
	return 0;
}

关于存储指针变量的vector的若干问题
可以看到,先将指针变量插入到vector中,然后再手动delete,那么vector中的元素所指向的内存空间会失效,但这却是一个非常良好的编程习惯,有new就必然有delete,不会造成内存泄漏。不过,这与我的初衷有悖,我想把1~10存入vector中,那么如何既保证功能又不会造成内存泄漏呢?

二、vector中指针变量的销毁

vector等一些容器在使用之后会自动调用析构函数,释放其占用的内存,那么我们是不是就不用管了,让析构函数完成释放内存的任务,请看下面代码。

int main()
{
	vector<int*> data;
	for (int i = 0; i < 10; ++i)
	{
		int* temp = new int(i + 1);
		data.push_back(temp);
	}
	cout <<  "data的size:" << data.size() << endl;
	cout << "data的capacity:" << data.capacity() << endl << endl;

	int* element0 = data[0];
	int* element1 = data[1];
	int* element2 = data[2]; // 保留前三个指针变量

	vector<int*> new_data;
	new_data.swap(data); // 与空的vector进行交换,释放原始vector内存
	cout << "data的size:" << data.size() << endl;
	cout << "data的capacity:" << data.capacity() << endl << endl;

	cout << "第1个元素:" << *element0 << endl;
	cout << "第2个元素:" << *element1 << endl;
	cout << "第3个元素:" << *element2 << endl;

	system("pause");
	return 0;
}

关于存储指针变量的vector的若干问题
可以看到,通过与空的vector进行交换(data与new_data交换),可以达到释放内存的效果,但是奇怪的是,data中原来存储的前3个指针变量所指向的内存空间依然存储有效值,这是为什么呢?究其原因,data在释放内存的时候并不会自动delete其中的指针变量,所以指针变量依然存储有效值,要想使得指针变量也被销毁,必须手动delete。所以在第一个例子中,要想达到保留数据的同时又不会造成内存泄漏的问题,必须在vector使用完之后,循环遍历其中的指针变量,将其手动delete,但是vector的内存释放不需要我们操心,它是通过自动调用析构函数来实现的。

三、结论

1、指针变量插入vector中,再手动delete,指针变量所指向的内存空间同样会失效。
2、vector在调用析构函数释放其内存的时候,并不会自动delete其中的指针变量,我们必须通过循环遍历的方式手动delete。但是对于存储类对象的vector,其中的对象会自动调用析构函数,这点与存储指针变量有很大的不同。