C++面试题

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  Parameter order  Clean-up Passes parameters  in registers?
pascal     Left-to-right    Routine                     No
cdecl      Right-to-left    Caller                      No
stdcall    Right-to-left    Routine                     No

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值