1. Macro
对于Macro只需要把握一点,Macro的机制是编译期的文本替换,而不是运行期的。这是它和函数最大的区别。因此要注意一下Block的使用(也就是{}和()一定要用 )。如果遇到对Macro行为的解释的题目,为了慎重起见,一定要先手工展开,再来进行别的方面的计算。
2. 指针/数组
没啥好说的,最常考的内容之一。主要是传值/传引用,sizeof,指针/数组在初始化上的区别。等等等。一个可能会出现的问题,是const的左绑定
3. 结构体/对象
在这一方面,常见的问题包括:内存对齐导致的sizeof和成员布局问题,bit field的正确使用,继承关系下的基类和派生类成员的分布。
4. 类
类方面的问题主要包括以下若干方面:
访问控制:public,private,protected,friend。对于这些,要有相对深刻的理解。你必须理解,访问控制仅在编译期有含义。在编译期之外,不会生成任何额外的代码,来保证你的访问正确性。
构造函数:要理解什么时候编译器会生成缺省构造函数,以及缺省构造函数的行为。对于一些测试代码风格的题目,千万不要忘了对拷贝构造、赋值的特殊处理,
以及对单值构造函数的explicit声明。explicit,和构造函数一起使用. explicit constructor指明构造函数只能显示使用,目的是为了防止不必要的隐式转化.
class X {
public:
explicit X(int); // 合法
explicit X(double) { //合法
// ...
}
};
explicit X::X(int) {} //不合法
void f(X) {}
void g(int I) {
f(i); // 错误,因为没有从int到X的隐式转换
}
void h() {
X x1(1); // 合法
}
注意多值构造使用explicit无意义,因为多值构造不进行隐式转换.
部分情况下,可能要考虑到成员/基类的构造顺序的问题。这个顺序是:先基类,后子类。本类中,声明序。不是按照初始化函数的顺序,而是按照声明的顺序。如果记不清,那就请记得把初始化函数的顺序和成员声明的顺序一致起来。
缺省的拷贝构造函数,它会只拷贝类的存储区的内容,如果其中有引用的话,它是不拷贝的,这就造成了,两个类的实例引用了同一个对象。
赋值运算符的一般形式是:T& operator=(const T& value),因为返回值是T&,所以可以连续赋值
析构函数:有两个地方是重中之重。第一,有虚函数的基类,一定要有一个虚析构函数。第二,不得抛出异常。
虚函数/非虚函数:这个主要可以参见书“Inside C++ Object Model”。虚函数的考点不外乎两点,底层实现和运行时行为。底层实现大部分的实现都是vptr - vtable的组合。
区别对象切割Object Slice和引用Reference(包括指针pointer)。
但通过派生类对象的指针或引用来调用虚函数,不发生对象切割,但直接将派生类对象传给基类型参数则发生对象切割。
CBase base;
CDerived derived;
base=derived;
Base& pBase = _derived; // Base* pBase = new Derived(); 等价于Base& pBase = _derived;也等价于 Base* pBase = &_derived;
在友元函数的函数体内访问对象成员时,必须用对象名加运算符“.”再加对象成员名,因为友元函数不属于任何类,所以必须用对象名加运算符“.”再加对象成员名
静态/非静态成员变量/成员函数:这里的考点比较多。他们在行为上的区别,存储上的区别,初始化的区别,访问的区别,指针的区别,
全局变量、静态全局变量、静态局部变量和局部变量的区别
变量可以分为:全局变量、静态全局变量、静态局部变量和局部变量。
按存储区域分,全局变量、静态全局变量和静态局部变量都存放在内存的静态存储区域,局部变量存放在内存的栈区。
按作用域分,全局变量在整个工程文件内都有效;静态全局变量只在定义它的文件内有效;静态局部变量只在定义它的函数内有效,只是程序仅分配一次内存,函数返回后,该变量不会消失;局部变量在定义它的函数内有效,但是函数返回后失效。
static 声明的变量在C语言中有两方面的特征:
1)、变量会被放在程序的全局存储区中,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与堆栈变量和堆变量的区别。
2)、变量用static告知编译器,自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。
Tips:
A.若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;
B.若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;
C.设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题;
D.如果我们需要一个可重入的函数,那么,我们一定要避免函数中使用static变量(这样的函数被称为:带“内部存储器”功能的的函数)
E.函数中必须要使用static变量情况:比如当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类型,则返回为错指针。
static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝
(函数)调用协议的区别是最常见的考点。
5. 类型和声明系统
主要考点在 const和volatile上。
一个罕见的关键字mutable的运用,也可能作为考点出现。被mutable修饰的变量,将永远处于可变的状态。
6.函数
有关于函数方面的问题,能考的点非常多。相对底层的包括调用协议(参数传递方法,入栈顺序,堆栈平衡等),应用级别的,主要还是考你栈和堆的区别。
__stdcall 、 __cdecl 、 __pascal 在什么方面有所不同。 (4 分 )
答:这些都是一些函数参数的调用约定,告诉编译器函数参数压栈的顺序,以及压入堆栈的内容由谁来清除,是调用者还是函数本身清除堆栈的内容。简单列表如下:
Directive
pascal
cdecl
stdcall