C/C++——你以为的指针?

写在前面

最近写了几个程序,都用到了指针,无一例外,都被坑了一把。。。特此进行总结,警醒自己,标题也很符合我当时的感觉,以为这就是指针,反而出了错。


场景

首先讲一下我的应用场景,到写这个总结的时候,我遇到的总共是两个场景:

  • 有一个公共的实例A,有很多B类的实例,B实例中包含了两个A的二维指针,其中每个B实例中的其中一个二维指针可能指向A实例,但是不可能都指向。
  • 函数外部有一个C的指针,初始化为NULL,函数的一个参数为C的指针,在函数内部对C的指针进行初始化。

以上就是促使我明白指针的两个场景,下面分别说一下两个场景中我犯的错误和对应的理解。

场景一

再该场景中,有人可能会问,为什么不在B中含有两个A的一维指针?笔者在进行写程序的时候(当然那时候还没有完全理解指针),其实是想在释放B的实例的时候,也释放掉A,当时以为如果使用一维指针,会有连续释放的问题,因此采用二维指针了,但是其实最后也有这样的问题,这件事也同时告诉了我二维指针的真相。
废话不多说,说一下我当时犯的错误,直接以代码的形式表示如下:

class A;
class B {
public:
	B(A* ptrA_) {
	// 错误1,这里完全错误
	m_ptrA = &ptrA_;
	// 错误2,其实这样写程序是对的,只不过不满足需求
	m_ptrA = new A*[1];
	*m_ptrA = ptrA_;
	}

private:
	A** m_ptrA=NULL;
};

A* ptrA = new A();
B* ptrB = new B(ptrA);

上面代码中,错误1是一个完全的错误,这里其实就涉及到指针的真实面目了,指针在传入不管是函数也好,还是对象的构造函数也好,传入的方式都是把该指针的内容给到函数中的参数中,在函数中之所以能调用一样的内容,是因为这两个不同的变量都指向同一个地址了,比如错误1的地方,程序在编译这个地方的时候,你会发现完全没有提示错误或者警告,但是如果你把所有的B对象放在一起,调试的时候会发现它们中的A二维指针指向的内容都是一样了,这是因为这样做的本质是让m_ptrA指向临时变量ptrA_的地址!所以这样做,必然会导致内存的泄露问题!而错误2的地方,其实是一个比较标准的写法,先给m_ptrA申请一个地址空间,随后将内容放了进去,注意了,假设B1和B2都指向A,假设地址为001,在释放B1的时候,虽然我们使用delete *m_ptrA;m_ptrA=NULL释放掉了001处的空间,但是在B2进行释放的时候,B2的m_ptrA中依然保留着内容,即A的地址001,所以在释放B2的时候,无疑会造成程序的崩溃。
所以,意识到不管是几维指针都是保留内容的这个事实之后,针对上面的应用,还是乖乖选择了智能指针帮忙管理了。

场景二

其实看了场景一的分析之后,场景二就很好理解了,下面是场景二的代码表示

int* p=NULL;

void give_value(int* p_) {
	p_ = new int;
	*p_ = 1;
}

give_value(p);

其实这个场景让我更加理解了为什么想要改变一个变量的值要用指针去传递的问题,本质上来讲,&value这样的方式传入是将地址作为内容*给了参数p_,p_是将这个p_的内容作为地址再拿出来,所以回到上面的场景中,调用give_value时,程序是将p的内容NULL给了p_,p_当然无所谓啊,你给什么就是什么咯,所以下面p_很听话的给自己的内容填上了new int的地址,之后又很听话的在这个地址上给了一个1的值,所以跟p有关系么?可以说半毛钱关系都没有了,因为p的内容依然是NULL!看到了么?这不是著名的C语言最基础的传参问题么?所以在C/C++中,指针也并不是什么特别特殊的存在,传入的时候,也是妥妥的按值传递,也按照正常的变量来对待就好啦~关键就是看传入进来的到底是什么值,也就是局部变量中携带的到底是什么。
理解了这个上述就很好解了,要么用二维指针,要么将int* p_改为int* &p_,也就是说我们把p_看作是传入参数的引用(影分身)。


总结

  1. 对于指针而言,并不能一直都认为它是指向什么地方的,只能说它携带了一个内容,这个内容是一个地方的地址;
  2. 对于指针的传递参数,依旧应该看作是按值传递,传入的内容是变量的地址。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值