volatile有什么作用?
-
volatile定义变量的值是易变的,每次用到这个变量的值的时候都要去重新读取这个变量的值,而不是读寄存器内的备份。
-
多线程中被几个任务共享的变量需要定义为volatile类型。
什么是常引用?
-
常引用可以理解为常量指针,形式为const typename & refname = varname。
-
常引用下,原变量值不会被别名所修改。
-
原变量的值可以通过原名修改。
-
常引用通常用作只读变量别名或是形参传递。
区别以下指针类型?
int *p[10]
int (*p)[10]
int *p(int)
int (*p)(int)
-
int *p[10]表示指针数组,强调数组概念,是一个数组变量,数组大小为10,数组内每个元素都是指向int类型的指针变量。
-
int (*p)[10]表示数组指针,强调是指针,只有一个变量,是指针类型,不过指向的是一个int类型的数组,这个数组大小是10。
-
int *p(int)是函数声明,函数名是p,参数是int类型的,返回值是int *类型的。
-
int (*p)(int)是函数指针,强调是指针,该指针指向的函数具有int类型参数,并且返回值是int类型的。
常量指针和指针常量区别?
-
常量指针是一个指针,读成常量的指针,指向一个只读变量。如int const *p或const int *p。
-
指针常量是一个不能给改变指向的指针。如int *const p。
a和&a有什么区别?
假设数组int a[10];
int (*p)[10] = &a;
-
a是数组名,是数组首元素地址,+1表示地址值加上一个int类型的大小,如果a的值是0x00000001,加1操作后变为0x00000005。*(a + 1) = a[1]。
-
&a是数组的指针,其类型为int (*)[10](就是前面提到的数组指针),其加1时,系统会认为是数组首地址加上整个数组的偏移(10个int型变量),值为数组a尾元素后一个元素的地址。
-
若(int *)p ,此时输出 *p时,其值为a[0]的值,因为被转为int *类型,解引用时按照int类型大小来读取。
数组名和指针(这里为指向数组首元素的指针)区别?
-
二者均可通过增减偏移量来访问数组中的元素。
-
数组名不是真正意义上的指针,可以理解为常指针,所以数组名没有自增、自减等操作。
-
当数组名当做形参传递给调用函数后,就失去了原有特性,退化成一般指针,多了自增、自减操作,但sizeof运算符不能再得到原数组的大小了。
野指针是什么?
-
也叫空悬指针,不是指向null的指针,是指向垃圾内存的指针。
-
产生原因及解决办法:
-
指针变量未及时初始化 => 定义指针变量及时初始化,要么置空。
-
指针free或delete之后没有及时置空 => 释放操作后立即置空。
-
堆和栈的区别?
-
申请方式不同。
-
栈由系统自动分配。
-
堆由程序员手动分配。
-
-
申请大小限制不同。
-
栈顶和栈底是之前预设好的,大小固定,可以通过ulimit -a查看,由ulimit -s修改。
-
堆向高地址扩展,是不连续的内存区域,大小可以灵活调整。
-
-
申请效率不同。
-
栈由系统分配,速度快,不会有碎片。
-
堆由程序员分配,速度慢,且会有碎片。
-
delete和delete[]区别?
-
delete只会调用一次析构函数。
-
delete[]会调用数组中每个元素的析构函数。