用右左法则来看,首先往变量a的右边看,是【3】,再往左看,是*,所以它首先是一个指针数组,数组里存放3个指针,然后再往右看是【4】,再往左看,是int *,说明前面3个指针每个指针都指向一个数组,每个数组里存放4个int 类型的指针,所以34有12个二级指针,每个指针在32位系统占4个字节,所以48个字节
p=NULL == p = 0 == p = ‘\0’,不可以用=\0来判断
对于内置类型而言,new仅仅是分配内存,除非后面显示加(),相当于调用它的构造函数,对于自定义类型而言,只要一调用new,那么编译器不仅仅给它分配内存,还调用它的默认构造函数初始化,即使后面没有加()
所以p2数组里面的元素都被初始化了,p1里面的只是被分配了内存
基类的公有成员,保护成员是其私有派生类的私有成员。
基类的公有成员,保护成员是其保护派生类的保护成员。
基类的公有成员,保护成员是其公有派生类的公有成员。
基类的私有成员对其派生类均不可见。
分情况看待:
1:字符串长度比设定长度大就按字符串实际长度输出;
2:字符串长度比设定长度小就按右对齐输出该字串,左补空格。
逗号表达式的结果就是后面的值!!y++=3,先输出3,再输出3
空指针调用虚函数,非虚函数是静态联编的
但是对于C++。为了保证程序的运行时效率,C++的设计者认为凡是编译时能确定的事情,就不要拖到运行时再查找了。所以C++的编译器看到这句话会这么干:
1:查找 pA 的类型,发现它有一个非虚的成员函数叫 test 。(编译器干的)
2:找到了,在这里生成一个函数调用,直接调A:: test ( pA )。
所以到了运行时,由于 test ()函数里面并没有任何需要解引用 pA 指针的代码,所以真实情况下也不会引发segment fault。这里对成员函数的解析,和查找其对应的代码的工作都是在编译阶段完成而非运行时完成的,这就是所谓的静态绑定,也叫早绑定。
正确理解C++的静态绑定可以理解一些特殊情况下C++的行为。
p 是个数组,所以 sizeof§ 返回数组的占用大小,64 位情况下
【char ** p[4] 】 表示 【char** 数组】 返回 4 * 8 = 32
【char * ( * p)[4] 】 表示 【指向 char* 数组的指针】 返回 8
【char (**p)[4] 】 表示 【指向 char 数组的指针的指针】 返回 8
假设线程x和y同时执行,x和y可随时被抢占,a的初始值为1
因为一个线程内要做两件事,分别是自加和输出两个操作,可能x自加后y抢占,然后y自加然后输出,然后x再输出,就是输出32
自加完之后没有写回内存,另一个线程就不知道别的线程修改过它了