前言
一些零碎的面试知识点,先放这里
基本知识回顾
已知strcpy函数的原型是:
char * strcpy(char * strDest,const char * strSrc);
1.不调用库函数,实现strcpy函数。
2.解释为什么要返回char *。
错误示例:
char * strcpy(char * strDest,const char * strSrc)
{
if(NULL == strDest)
{
return NULL:
}
if (NULL == strSrc)
{
return strDest;
}
if (NULL != strSrc)
{
strDest++ = strSrc++;
}
*strDest = '\0';
}
参考答案:
char * strcpy(char * strDest,const char * strSrc)
{
if ((strDest==NULL)||(strSrc==NULL)) //[1]
throw "Invalid argument(s)"; //[2]
char * strDestCopy=strDest; //[3]
while ((*strDest++=*strSrc++)!='\0'); //[4]
return strDestCopy;
}
注意点:
1:检查指针的有效性,注意隐式的类型转换,用NULL来检查比较合理
2:异常的处理,不管是源还是目的指针,为空都抛出异常。或者return NULL
打印异常:terminate called after throwing an instance of 'char const*'
3:函数返回值,保存目的字符串的起始位置返回,不是源字符串,这样可以使函数支持链式表达式
链式表达式:
int iLength=strlen(strcpy(strA,strB));
char * strA=strcpy(new char[10],strB);
4:最简洁的语句
while (*strDest++=*strSrc++);
链接
1.求下面函数的返回值
int countx = 0;
while(x)
{
countx ++;
x = x&(x-1);
}
return countx;
参考答案:
while循环每次把2进制的右边的1消除,返回值是循环的次数,循环的次数是x的二进制位中包含1的个数
2.什么是“引用”?声明和使用“引用”要注意哪些问题?
参考答案:
引用就是某个目标变量的“别名”,对引用的操作与对变量直接操作效果完全相同
声明一个引用的时候,切记要对其进行初始化
它本身不是一种数据类型,因此引用本身不占存储单元
网上有的地方说数组不能引用,其实是可以的,参考: 关于数组的引用和引用的数组
//数组的引用
int a[10] ={0};
int (&b)[10] = a;
网上有的地方说引用一经定义,就不可更改,但是我用vs2017是可以的:
int a = 1;
int c = 2;
int & b = a;
b = c;
3.将“引用”作为函数参数有哪些特点?
类似指针,不同于传值调用会自动创建临时变量副本,提高效率
不同于指针,传入指针,函数也会申请临时的指针变量存放实际变量的地址,而引用不会.且引用的可读性更好
4.在什么时候需要使用“常引用”?
如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。常引用声明方式:const 类型标识符 &引用名=目标变量名;
//有点像是常量指针
int a ;
const int &ra=a;
ra=1; //错误
a=1; //正确
int main()
{
string foo();
void bar(string & s);
bar(foo()); //错误,非常量引用的初始值必须是左值 无法从const string 转换为 string &
bar("hello world"); //错误,利用拷贝构造函数会生成const string,但无法转为string &
//改成bar(const string & s)就好了
}
5.“引用”与指针的区别是什么?
6.线程与进程的区别
进程和线程都是一个时间段的描述,是CPU工作时间段的描述,不过是颗粒大小不同
线程是共享了进程的上下文环境,的更为细小的CPU时间段