重拾C++经典笔试30题（1-10）

1.统计10进制转化为2进制1的个数

int total2Cnts(int x)
{
int count = 0;
while(x)
{
++count;
x = x&(x-1);
}
cout << endl;
return count;
}

int main()
{
int num = 9999;
for( int i = 0; i < 100; i++)
{
cout << i <<"中1的个数为:" <<total2Cnts(i) << endl;
}

return 0;
}

2.浮点转换

int main()
{
float a = 1.0f;
cout << (int)a << endl;
cout << &a << endl;
cout << (int&)a <<endl;
cout << boolalpha << ((int)a == (int&)a ) << endl; //false

float b = 0.0f;
cout << (int)b << endl;
cout << &b << endl;
cout << (int&)b <<endl;
cout << boolalpha << ((int)b == (int&)b ) << endl; //true
return 0;
}

3.位运算

#include<iostream>
usingnamespace std;
intmain()
{
char a = 'a';
char b = ~a;
cout<<sizeof(a)<<endl;                //1
cout << typeid(a).name() <<endl;        // char
cout<<sizeof(b)<<endl;                //1
cout << typeid(a).name() <<endl;        // char
cout<<sizeof(~a)<<endl;                  //4
cout << typeid(~a).name() <<endl;        // int
cout<<sizeof(a&b)<<endl;                //4
cout << typeid(a&b).name()<< endl;        // int

return 0;
}

4.输入输出流与printf在多线程中的区别和影响

int g_cnt;
unsignedint _stdcall ThreadProc1(PVOID lpParameter)
{
g_cnt++;
printf("subThreadis running! g_cnt = %d\n",g_cnt);
//       cout << "subThread is running!g_cnt = " << g_cnt << endl; //此处和printf打印在多线程操作中的区别？
return 0;
}

int main()
{
g_cnt = 0;
const int nThreadNum = 5;
//Caution...!
for( int i=0; i < nThreadNum; i++)
{
}

return 0;

}

5.位运算

X&Y指取出X与Y的相同位；

X异或Y取出X与Y的不同位；

X右移1等价于X除以2。

X左移1等价于X乘以2.

//取出a,b中较大者。

intmaxFun(int a, int b)
{
return (((a+b) + abs(a-b))/2);
}

//a,b交换操作
voidexchange(int& a, int& b)
{
a = a^b;
b = a^b;
a = a^b;
}

6.     求解结构体偏移量的方法？

#define FIND(STRUC, e)(size_t)&(((STRUC*)0)->e)
structstudent
{
int a;
char b[20];
double c;
};//32

intmain()
{
cout << FIND(student,a) <<endl; //0
cout << FIND(student,b) <<endl; //4
cout << FIND(student,c) <<endl; //24

cout << sizeof(student) <<endl; //32
return 0;
}
#define FIND(STRUC, e)(size_t)&(((STRUC*)0)->e)

7.注意以下的表示方法！

#define SECONDS_PER_YEAR 365UL*24UL*3600UL用法值得商榷！

#defineMIN(a,b) ((a)<=(b) ? (a):(b))

8.const与define对比？

constdefine1.是否具有类型？有类型没有类型2.是否进行安全检查？编译器有安全检查仅是字符替换3.是否可调试？可调试不可调试

优点缺点及注意点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的成员函数就可以修改它了。

classmutClS
{
public:
mutClS(int nx):m_x(nx) {}
~mutClS(){}
void increase( int incx) const
{
m_x += incx;
}
void decrease(int decx) const
{
m_x -= decx;
}
void display()
{
cout << m_x <<endl;
}
private:
mutable int m_x; //注意此处！
};

intmain()
{
mutClS objA(35);
objA.increase(5);
objA.display();

objA.decrease(5);
objA.display();

return 0;
}

10.  C++对象的内存布局

class simpleClass
{
public:
simpleClass(){}
virtual ~simpleClass() {}

int getValue(){}
virtual void fool(){}

static int nCount;
int nValue;
char c;
};

int main()
{
simpleClass aSimple;
cout << "Object startaddress:\t" << &aSimple << endl; //0012FF68
cout << "nValueaddress:\t" << &aSimple.nValue << endl; //0012FF6C
printf("c address: %x\n",&aSimple.c); //0012FF70
cout << "size: "<< sizeof(simpleClass) << endl; //12
return 0;
}

&aSimple= 0012FF68；即虚函数表指针占据的一个对象开始的4个字节。

（1）非静态数据成员是影响对象占据内存的主要因素，随着对象数目的增多，非静态数据成员占据的内存也会相应增加。

（2）所有的对象共享一份静态数据成员，所以静态数据成员占据的内存的数量不会随着对象数目的增加而增加。

（3）静态成员函数和非静态成员函数不会影响对象内存的大小，虽然其实现会占据相应的内存空间，同样也不会随着对象数目的增加而增加。

（4）如果对象中包含虚函数，会增加4个字节的空间，不论有多少个虚函数。

——摘自《C++应用程序性能优化》（第2版）P25

class derivedClass :public simpleClass
{
public:
derivedClass(){}
~derivedClass(){}
int nSubValue;
};

class A
{

};
class B
{
};

class C : public  A
{
};

class D : virtualpublic  B //4
{
};

class E : public  A, public B
{
};

int main()
{
cout << sizeof(A) << endl; //1
cout << sizeof(B) << endl; //1
cout << sizeof(C) << endl; //1
cout << sizeof(D) << endl; //4[涉及虚拟继承（虚指针）]
cout << sizeof(E) << endl; //1
return 0;
}

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;
}

class midClass1 : publicbaseClass //仅是增加了nMidValue1，扩展为16字节

class midClass2 : publicbaseClass //仅是增加了nMidValue2，扩展为16字节

classderivedClass :  public midClass1,  public midClass2 //在继承midclass1，midclass2基础上仅是增加了subVal，为16+16+4=36字节。

VisualC++添加了了虚拟基类表指针来实现虚拟继承，类中只要有visual函数就会产生这个vtb 虚函数表和一个vptr虚函数指针,它们都会占内存的。

【已解决】主要原因，VisualC++添加了了虚拟基类表指针来实现虚拟继承，因此，空间变大？实际怎么多了8个字节。

baseClass类包含1个虚函数表指针（4个字节）、1个int型数据成员（4个字节）、1个char型数据（对齐后4个字节）成员，共12个字节。midClass1同midClass2一致，需要在baseClass类的基础上，多了1个虚函数表指针（4个字节）、1个指向虚基类表的指针（4个字节）、一个整形数据成员（4个字节），合计共12+12 =24个字节。

derivedClass 在上述的基础上，包含baseClass(12个字节)、midClass1(新增12个字节)、midClass2(新增12个字节)、derivedClass的1个整形数据成员（4个字节），合计共40个字节。注意derivedClass是继承而非虚拟继承自两个父类，所以没有指向虚基类表的指针。

+ 订阅