重拾C++经典笔试30题(1-10)
重拾C++经典笔试30题(1-10)
1. /*----------------统计10进制转化为2进制1的个数-----------------
const
define
1. 是否具有类型?
有类型
没有类型
2. 是否进行安全检查?
编译器有安全检查
仅是字符替换
3. 是否可调试?
可调试
不可调试
内联函数与define宏定义对比?
优点
缺点及注意点
Define宏定义
1.提高了运行效率
1.不可调试,无法进行安全检查(类型)
2.可能出现边际效应导致出错。
3.不能操作类的私有数据成员。
内联函数
1提高效率及安全性;
2编译器可以用上下文优化技术继续对结果代码优化。
1每一次内联处都要拷贝代码,使程序总工作量大;
2.短小、 简单函数设为内联(重复调用,无switch、for、while)等语句;
3.不要将构造、析构函数设置为内联函数。
9. 不常用的mutalbe关键字
[MSDN]mutable
C++Specific —>mutable member-variable-declaration;
Thiskeyword can only be applied to non-static and non-const data members of aclass. If a data member is declared mutable, then it is legal to assign a valueto this data member from a const member function.
解读:mutable成员变量的声明,这个关键字只能应用于类的非静态与非const数据成员。如果一个数据成员声明为mutable,那么通过const成员函数给数据成员分派一个值是合法的。
[作用]:加mutable关键字的成员变量,修饰为const的成员函数就可以修改它了。
不加mutable,会报错:l-value specifies const object。
类别
类型
存储类别
占内存情况
数据成员
static int nCount;
全局/静态存储区
不作为对象占据内存的一部分
int nValue;
char c;
非静态数据成员
栈存储区
根据地址对齐,二者占用8字节空间。
成员函数
static void addCount(){}
C++编译器采用普通与C函数类似的方式进行编译,只不过对函数进行了名字修饰(name mangling),用来支持重载;并且在参数列增加了一个this指针,用来表明哪一个对象调用的该函数。
静态和非静态成员函数的多少对对象的大小没有影响。
int getValue(){}
构造、析构函数、拷贝构造
virtual void fool(){}
C++编译器在碰到虚函数的类时,会分配一个指针指向一个函数地址表,叫做“虚函数表”。
占4个字节,虚函数表指针占据的4个字节。
看下面注释的结果值,再分析:
class baseClass{public: virtual void fool(void) {} int nValue; char c;}; class midClass1 : virtualpublic baseClass{public: virtual void setVal(){} int nMidValue1;}; class midClass2 : virtualpublic baseClass{public: virtual void setVal(){} int nMidValue2;}; class derivedClass : public midClass1, public midClass2{public: virtual void foo2(){} int subVal;};int main(){ cout << sizeof(baseClass) << endl; //12 cout << sizeof(midClass1) << endl; //24 cout << sizeof(midClass2) << endl; //24 cout << sizeof(derivedClass) << endl; //48 return 0;}已经知道的,对于baseClass类的大小,考虑地址对齐为4(c)+4(nvalue)+4(虚拟函数指针)共12个字节;
如果去掉虚拟继承,为如下形式:
class midClass1 : publicbaseClass //仅是增加了nMidValue1,扩展为16字节
class midClass2 : publicbaseClass //仅是增加了nMidValue2,扩展为16字节
classderivedClass : public midClass1, public midClass2 //在继承midclass1,midclass2基础上仅是增加了subVal,为16+16+4=36字节。
不理解点:为什么加了虚拟继承,sizeof(midClass1)= 24;sizeof(midClass2)=24;sizeof(derivedClass)48;
主要原因,VisualC++添加了了虚拟基类表指针来实现虚拟继承,类中只要有visual函数就会产生这个vtb 虚函数表和一个vptr虚函数指针,它们都会占内存的。
具体为什么增加了8个字节,希望与大家探讨!