详谈C++指针(2、指针与变量的生命周期)

          上一篇文章《C++指针到底是什么》当中就提到过,C++当中的指针存放的是某个数据的地址,指针的类型只是告诉系统应该怎样处理地址下的数据。当然就算是地址下的数据以及消失不在了,指针依然记录着当时数据的指针,所以我们依然可以使用数据去访问,但是到底会发生什么样的结果,恐怕是很难预测了。

1、对于已经释放的数据的地址指针依然可以访问

        虽然说内存的当中的数据已经释放掉了,但是内存的地址是肯定不会变动的,所以指针对当前地址下的内存任然可以继续访问,请看下面的案例

先定义一个Book类型

#ifndef BOOK
#define BOOK
struct Book{
	std::string mName;
	int mID;

	Book(const std::string& iName, int iID);
	~Book() { std::cout << "destroy function has be called" << std::endl; };
};

Book::Book(const std::string& iName, int iID) :mName(iName), mID(iID) {}
#endif // !BOOK

测试代码如下

int main() {
	Book book1("简爱",1);
	Book* pVar = nullptr, *pVar2 = nullptr;

	pVar = &book1;

	std::cout << "pVar -> Name is " << pVar->mName << std::endl;

	{
		Book book2("活着",2);
		pVar2 = &book2;
	}

	std::cout << "pVar2 -> Name  is " << pVar2->mName << std::endl;
	std::cout << "pVar2 -> ID is " << pVar2->mID << std::endl;

	Book* pVar3 = new Book("鼠疫",3);

	delete pVar3;

	std::cout << "pVar3 -> ID is " << std::endl;
	std::cout << "pVar3 -> Name is " << pVar3->mName << std::endl;

	return 0;
}

运行结果如下

我们可以看到,book2,book3的名称没有能打印出来,甚至book3的id号也没有打印出来,这里可以看到虽然指针依然能够去访问地址下的内存,但是很明显没有得到我们想要的结果。有人可能在意为什么book2,book3的打印的结果不相同,这里只能说:因为这是一种不定义的行为发生什么事都是有可能的,就算事同样的一段代码,在不同的解释器的下运行出来的结果都很可能完全不一样。

2、难以管理的指针

        当然很多人看到上面的案例就表示自己肯定不会去写这种不定义行为的代码,不过很多我们会在无意之下写出这种代码,请看下面的案例

void AddBook2Library(std::vector<Book*>& library,Book* pBook);
void RealeBook(Book* pBook);

int main() {
	Book *pVar = nullptr, *pVar2 = nullptr, *pVar3 = nullptr;

	pVar = new Book("简爱", 1);
	pVar2 = new Book("活着",2);
	pVar3 = new Book("鼠疫",3);

	std::vector<Book*> library;
	library.reserve(3);

	//将书籍添加到library容器当中
	AddBook2Library(library, pVar);
	AddBook2Library(library, pVar2);
	AddBook2Library(library, pVar3);

	//突然想到第二本书不需要
	RealeBook(pVar2);

	//这个时候指向第二本书的指针并没有从library容器当中移除
	//但是想要查看一下library当中的第二本书是什么
	std::cout << "second book is " << library[1]->mName << std::endl;
	return 0;
}

void AddBook2Library(std::vector<Book*>& library, Book* pBook) {
	library.emplace_back(pBook);
}

void RealeBook(Book* pBook) {
	delete pBook;
}

运行的结果如下

显然这并不事我们想要的结果。

        这种结果是,在某个地方释放了指针,但是在另一处使用的并没有考虑到这个地址下的数据已经被释放而导致的。

        当然案例当中展示都是去读数据,如果是写入的话就更危险了,很可能将其它有用的数据写坏掉。

3、因该放弃使用指针吗?

        很显然造成这种问题的原因是,指针对于在堆中的内存需要我们手动去释放,不然会造成内存的溢出。现在的C++都引入了智能指针,我们再也不用手动去管理这些变量,这减少了我们很多的痛苦,这是好事。但是我们就应该完全放弃传统指针吗?笔者认为对于这是还是不能过于极端,我们知道C++的智能指针其实是一个模板类,并不是真正意义上的指针,而传统指针就是一个整型的数据,传统指针无论是在定义上还是在传递上都很高效。如果说在项目当中这些传统指针也是很容以进行管理的,那为什么非要用智能指针不可了?

4、总结

        C++指针功能很强大,但是在使用的时候要小心谨慎,使用指针读写数据的时候一定要考虑变量的生命,如果对于当前的项目而言传统指针实在难以管理,就可以考虑使用智能指针,但是传统指针依然有自己的优势,我们因该视具体的情况来使用传统指针和智能指针。

  • 17
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值