目录
不同类型所产生的指针在C++语言中有什么作用?带着这个疑问,对C++的指针进行简介。
1.问题描述及分析
在如下的一段代码中,分别有4个指针,这四个指针有什么不一样的地方么?
cpp
class ZooAnimal
{
public:
ZooAnimal();
virtual ~ZooAnimal();
//...
virtual void rotate();
protected:
int loc;
string name;
};
ZooAnimal za("Zoey");
ZooAnimal *pza = &za;
int *pi;
Array<string> *pta;
void *ptv;
就内存需求的观点而言,没有不同,他们需要有足够的内存存储一个机器地址,在32位系统中就是32bit。
就所寻址的object是不同,也就是说"指针类型"会教导编译器如何解释某个特定地址中的内存大小和内容。
1)一个指向地址int的整数指针,在32位的机器上,所涵盖的地址是1000-1003,因为32位机器上是4Bytes。
2)如果string是传统的8Bytes,那么一个ZooAnimal指针横跨地址空间1000-1015,见下图4+8+4。
对于指向1000的void *指针,地址空间大小和内容我们是不知道的。转换(cast)是一个编译器指令,大部分情况并不改变指针所含有的真正地址。
现在,我们定义一个Bear,他public继承ZooAnimal,我们看看如下的代码的指针作用。
cpp
class Bear : public ZooAnimal
{
public:
Bear();
~Bear();
//...
void rotate();
virtual void dance();
//...
protected:
enum Dances{...};
Dances dances_known;
int cell_block;
};
Bear b("Yogi");
Bear *pb = &b;
Bear &rb = *p;
b,pb,rb的内存布局是什么样子的?可以看出Bear object需要24Bytes,也就是ZooAnimal的16Bytes加上Bear所带来的8Bytes。
除了解释对象的布局外,还有对象的member function访问情况也需要进一步的说明。由于对象的指针,存在作用域,它会根据作用域调用member function。
cpp
Bear b;
ZooAnimal *pz = &b;
Bear *pb = &b;
//不合法,cell_block不是ZooAnimal的一个member,
//虽然我们知道pz目前指向一个Bear object
pz->cell_block;
//ok,经过一个显示的downcast操作就没有问题
(static_cast<Bear *>(pz))->cell_block;
//下面这样更好,但它是一个run-time operation(成本高)
if(Bear *pb2 = dynamic_cast<Bear *>(pz))
pb2->cell_block;
//ok,因为cell_block是Bear的一个member
pb->cell_block;
//将调用Bear的rotate方法
pz->rotate();
2.结论
C++指针的作用主要有两点:
1)"指针类型"会教导编译器如何解释某个特定地址中的内存大小和内容(包含member data),生成固定的内存布局。
2)"指针类型"会教导编译器如何访问member function。