[cpp primer随笔] 02.复合类型

1. 复合类型声明的理解

一条声明语句由基本类型和声明符组成。基本数据类型的声明符等同于变量名。而如果对变量名予以修饰,就会得到一个复合类型,常见的有指针和引用。
[cpp primer随笔] 02.复合类型_第1张图片
在声明指针的时候,将指针符号与基本数据类型或变量名连着写的人都有。

int *i;
int* j;

基于声明语句的结构,我更习惯于第一种,因为我认为声明符连在一起更顺眼些。这种感觉在连续声明指针的时候尤为明显。当然,这是个人喜好。

int *i, *j;	// i, j是指针
int *i, j;	// i是指针,j是整型

2. 引用与指针的底层原理

引用和指针在编译成汇编后,均表现为一块存储着其所绑定对象地址的内存空间。然而二者在进行操作时却有着截然不同的表现。

引用在定义后无法绑定其他对象,因为一切对引用的操作无法直接作用在该内存空间上,而是会将该内存空间存储的对象地址读到寄存器中,再对该地址指向的对象进行进一步读写操作。这就是引用的本质。

而对指针的操作都是直接对该内存空间本身进行操作。只有当使用*解引用符时,指向元素的地址才会被拿到寄存器上操作(即操作该指针指向的对象)。

下面我写两个函数,编译成汇编代码。

void refrence(){
    int c = 1;
    int &cc = c;
    cc = 2;
}

void pointer(){
    int c = 1;
    int *d = &c;
    d = 0x0;
    *d = 5;
}

[cpp primer随笔] 02.复合类型_第2张图片

3. 指针细节

  • 指针的类型应当与其指向变量的类型一致,否则会引发错误。例如:
 double j = 114.514;
 int *i = j;	// error
  • 指针初始化时,可以给指针初始化为nullptr(C++ 11),可以初始化为NULL(需包含),也可以让其等于0,但是不能给其赋值一个为0的基本类型。

4. void*

作为一种特殊的指针,void*也可以用于指向一块内存空间。不同的是,程序无法通过该指针知晓那块内存空间的数据类型,继而无法做出有效的读写操作。

struct A{
	void out(){} //do something ...
}
void *a = new A();
a.out(); // error

如果程序员知道一个void*指针指向对象的类型,可以用将该指针进行类型转换,进而可以操纵这个对象。

A* b = a;
b.out(); // success

5. 指针引用

引用不是对象,因此不存在引用指针这种东西。但指针是对象,因此一个引用可以绑定一个指针,就像下面这样:

int *p = nullptr;
int *&r_p = p; // 指针引用

指针引用的声明符看上去很复杂。cpp primer讲了一种理解方式我觉得很好。判断一个变量类型,要从它声明语句最接近变量名的那个符号开始,自右向左读。在上面的例子里,r_p是变量名,最近的符号为&,因此它是一个引用,一个与int *类型做绑定的引用,以此类推。

你可能感兴趣的:(C++,c++)