C++程序员面试宝典——基本概念易错题

来源:互联网 发布:python代码示例 编辑:程序博客网 时间:2024/05/16 08:19

1.万能的异或 

x&y+((x^y)>>1)  //表示取两个数的平均值。

x^y+((x&y)<<1)//表示取两个数的和。

a=a^b; b=a^b; a=a^b//交换a,b。不必担心越界问题。

异或^,C中虽然没有同或操作符,但由逻辑关系知同或是异或的非,所以d=!(a^b)。

2. 判断一个字符串中的字符是否都在另一个中出现

判断一个字符串中的字符是否都在另一个中出现:

(1) 哈希表法:每个字母都放入一个Hashtable,轮询第二个字串,在Hashtable里查询每个字母,看能否找到。

(2) 素数乘除法:每个字母分配一个素数,遍历第一个字串,把每个字母代表的素数相乘。最终得到一个很大的整数。

轮询第二个字符串,用每个字母除它。如果除的结果有余数,这说明有不匹配的字母。

(3) 逻辑或与异或法:C=A|B(按位或) ;D=A^C(按位异或)。D为0那么说明B中的字符串在A中都出现

3. C中printf计算参数时,是从右到左压栈

printf("%d, %d\n", *ptr, ++*ptr)

4. 逻辑运算

与运算计算时,第一个不符合则不对第二个进行判断。

或运算计算时,第一个符合则不对第二个进行计算。for(a=0,x=0; a<=1 && !x++; a++)  

5. if('A'==a) 比if(a=='A')好。因为写错成“=”可以检测出来。

6. 输出地址陷阱

float a=1.0; cout<<(int &) a;  //将a地址的前sizeof(int)个字节当成int型的数据输出。

7. 单位

32位机器上:

sizeof(void*)= 4;

64位机器上:

sizeof(char)= 1;signed char=1; sizeof(bool)= 1;sizeof(wchar_t) = 2;

sizeof(short)= 2;sizeof(unsigned int)= 4;sizeof(int)= 4;sizeof(long)= 4;sizeof(long long) = 8;

sizeof(float)= 4;sizeof(double)= 8;sizeof(long double)=16

sizeof(void*)= 8;

16位系统:long是4字节,int是2字节、

32位系统:long是4字节,int是4字节

64位系统:long是8字节,int是4字节

8. 指针。

char* b=(char*) &a;// 指针指向a,指针类型是char型。a+1=x+1*sizeof(int); b+1=x+1*sizeof(char)

int *p=0;//空指针

把int型数据传给函数f(double), 则调用的形参将int转化为double型。

函数返回值类型与函数类型不同,自动被转化为函数类型。

9. cout与printf

c中的printf和c++中的cout完成的功能一样,都是输出,书写格式不一样
(1). 格式不同int a=6; cout<<a<<endl; printf("%d\n",a)

(2). printf是函数。cout是ostream对象,和<<配合使用。

(3). c++中也能使用printf,但是c中不能使用cout

10. 运算符优先级

unsigned char b=~a>>4.   编译器会先将a和4提升为整形,再对a取反,右移5位。

(1) 涉及类型提升。所有小于整型的有序类型数据,在算术表达式计算之前其类型都会被转换为整形。

(2) +的优先级比>>高。

11. 为什么C++中引用这么重要?

(1)在引用的使用中,单纯给某个变量取个别名是毫无意义的,引用的目的主要用于在函数参数传递中,解决大块数据或对象的传递效率和空间不如意的问题。

(2)用引用传递函数的参数,能保证参数传递中不产生副本,提高传递的效率,且通过const的使用,保证了引用传递的安全性。

(3)引用与指针的区别是,指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。

(4)使用引用的时机。流操作符<<和>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用。

引用与一些操作符的重载:

流操作符<<和>>,这两个操作符常常希望被连续使用,例如:cout << "hello" << endl; 因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。可选的其它方案包括:返回一个流对象和返回一个流对象指针。但是对于返回 一个流对象,程序必须重新(拷贝)构造一个新的流对象,也就是说,连续的两个<<操作符实际上是针对不同对象的!这无法让人接受。对于返回一 个流指针则不能连续使用<<操作符。因此,返回一个流对象引用是惟一选择。这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这 就是C++语言中引入引用这个概念的原因吧。 赋值操作符=。这个操作符象流操作符一样,是可以连续使用的,例如:x = j = 10;或者(x=10)=100;赋值操作符的返回值必须是一个左值,以便可以被继续赋值。因此引用成了这个操作符的惟一返回值选择。

【例6】 测试用返回引用的函数值作为赋值表达式的左值。

#include <iostream.h>
int &put(int n);
int vals[10];
int error=-1;
void main()
{
put(0)=10; //以put(0)函数值作为左值,等价于vals[0]=10;
put(9)=20; //以put(9)函数值作为左值,等价于vals[9]=20;
cout<<vals[0];
cout<<vals[9];
}
int &put(int n)
{
if (n>=0 && n<=9 ) return vals[n];
else { cout<<"subscript error"; return error; }
}

在另外的一些操作符中,却千万不能返回引用:+-*/ 四则运算符,它们不能返回引用,Effective C++[1]的Item23详细的讨论了这个问题。主要原因是这四个操作符没有side effect,因此,它们必须构造一个对象作为返回值,可选的方案包括:返回一个对象、返回一个局部变量的引用,返回一个new分配的对象的引用、返回一 个静态对象引用。根据前面提到的引用作为返回值的三个规则,第2、3两个方案都被否决了。静态对象的引用又因为((a+b) == (c+d))会永远为true而导致错误。所以可选的只剩下返回一个对象了。

0 0