C++指针(3)


四、void*指针


void* 指针是C++提供的一种特殊的指针类型,他可以保存任何类型对象的指针:

double obj = 3.14;
double *pd = &obj;

void *pv = &obj;
pv = pd;

以上关于void* 指针 pv 的定义都是合法的。

void* 表明该指针与一地址值相关,但不清楚存储在此地址上的对象的类型。


void* 指针只支持几种有限的操作: 与另一个指针进行比较;向函数传递 void* 指针或从函数返回 void* 指针; 给另一个 void* 指针赋值。 不允许使用 void* 指针操纵它所指向的对象。



五、指针和引用的比较


指针和引用(reference)都可间接访问一个值,但他们之间有2个重要区别:

1. 引用总是指向某个对象:定义引用时没有初始化是错误的。

2. 赋值行为的差异:给引用赋值修改的是该引用所关联的对象的值,而并不是使引用与另一个对象关联。引用一经初始化,就始终指向同一个特定对象。


给出以下例子说明:

#include <iostream>
 
using namespace std;
 
int main(){
        int ival1 = 1024, ival2 = 2048;
        int *pi1 = &ival1, *pi2 = &ival2;
        
        cout << ival1 << endl;
        cout << ival2 << endl << endl;
        
        cout << *pi1 << endl;
        cout << *pi2 << endl << endl;   
        
        cout << pi1 << endl;
        cout << pi2 << endl << endl;
 
        
        pi1 = pi2;
        
        cout << ival1 << endl;
        cout << ival2 << endl << endl;
        
        cout << *pi1 << endl;
        cout << *pi2 << endl << endl;   
        
        cout << pi1 << endl;
        cout << pi2 << endl << endl;
        
        pi1 = &ival1;
        int &ri1 = ival1, &ri2 = ival2;
        ri1 = ri2;
        
        cout << ival1 << endl;
        cout << ival2 << endl << endl;
 
        cout << pi1 << endl;
        cout << pi2 << endl << endl;
        
        return 0;
}

上面代码输出如下:



注意到,当执行

pi1 = pi2;

后,pi1 指向的对象不再是 ival1, 而是 ival2。

之后执行的代码

        
        cout << *pi1 << endl;
        cout << *pi2 << endl << endl;   
        
        cout << pi1 << endl;
        cout << pi2 << endl << endl;

验证了这一点。无论是 *pi1 还是 *pi2, 输出的也是 ival2 的值。 而 pi1, pi2存储的也是 ival2 的地址。


但对于引用 ri1 和 ri2,当执行代码

        int &ri1 = ival1, &ri2 = ival2;
        ri1 = ri2;

后,ival1 的值就变成了 ival2的了。


ri1 绑定的对象是 ival1, 当对 ri1 进行赋值, 那并不会使得 ri1 解除对 ival1 的绑定,反而是使得 ri1 绑定的对象 ival1 的值被修改。

之后的代码也验证了这点。

        cout << ival1 << endl;
        cout << ival2 << endl << endl;
 
        cout << pi1 << endl;
        cout << pi2 << endl << endl;

通过检查 pi1 和 pi2 的输出, ival1 的地址并没有改变,改变的只是该地址上存储的内容。



六、指针的指针


指针本身也是可用指针指向的内存对象。指针占用内存空间存放其值,因此指针的存储地址可存放在指针中。下面程序段:

int ival = 1024;
int *pi = &ival;
int **pi = π

定义了指向指针的指针。 C++ 使用 ** 操作符指派一个指针指向另一个指针, 即 pi 的内存空间存储了 ival 的地址, 而 ppi  的内存空间则存储了 pi 的地址。图示可表示如下:



在这里注意一点,假如一个指向 “指针的指针”的指针,那如何定义呢? 用 *** 符号?

答案是 是的


如下对指针的定义是合法的:

	int ival = 1024;
	int *p1 = &ival;
	int **p2 = &p1;
	int ***p3 = &p2;

可能有人会认为, p2 其实也是一个指针, 那 p3 假如要指向 p2, 那 p3 应该就是一个指向指针的指针, 用 ** 符号能够操作正确,那我们执行下面定义

	int **p3 = &p2;

程序编译会提示如下错误:


&p2 是一个 int*** 类型, 他无法被转换为 int** 类型;


那么,执行如下代码呢?

#include<iostream>

using namespace std;

int main(){
	int ival = 1024;
	int *p1 = &ival;
	int **p2 = &p1;
	int ***p3 = &p2;
	int **p4 = (int**) &p2;
	
	cout << p3 << endl;
	cout << p4 << endl << endl;
	
}

输出结果如下:


从输出结果可见, p3 和 p4 均存储了 p2 的地址, p4 的类型是 int**, 但这里用到了强制类型转换

这个过程看似可以,可假如要通过 p4 取 ival 的值,那应该 *(*p4) 还是 *(*(*p4)) ?

执行如下代码:

	cout << *(*p4) << endl;
	cout << ival << endl;

输出结果如下


可见, *(*p4) 并不能获取 ival 的值。实际上,通过以下执行以下代码:

	cout << p1 << endl;
	cout << hex << *(*p4) << endl;

输出如下:


可见,实际上 *(*p4) 输出的是 ival 的地址, 而不是 ival 的值。

要获得 ival 的值, 应该执行以下代码:

	cout << *((int*)(*(*p4))) << endl;
先将 *(*p4) 结果 强制转换成 (int*) 类型后再解引用。



另外,假如执行

	cout << *(*(*p4)) <<  endl;

则会直接提示错误

因为 p4 并不是一个 int*** 型



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值