剑指offer--面试题1
为了准备实习面试,最近开始看《剑指offer》, 以前挺反感这种有投机性质的书。但是为了拿到个好offer,也顾不了那么多了。
第一道题是考 基础知识 里面的编程语言。C++基本是每个应聘者都需要掌握的语言吧,因为一般在草纸上写代码都是C或者C++的。
对于C++来说,类的定义和结构,以及继承,派生,多态是面试中常被问到的, 而面试题1就考察了应试者对C++中赋值运算符的理解。
一般来说,C++中的一个空类会默认生成以下函数。
1:默认构造函数
2:默认拷贝构造函数
3:默认赋值操作符
4:默认虚构函数
5:取值操作符.
如
class A
{
A();
A(const A &lhs);
A& operator=(const A &lhs);
~A();
A* opeator&();
}
至于每个函数的作用 《C++ primer》中有很详细的讲解。
而这里需要强调的是 sizeof(A) = 1, 这是因为我们声明类型的实例时,它必须在内存中占有一定的空间,至于占多少内存,是由编译器决定的,VS中每个空类型的实例占用1字节的空间。
面试题1: 如下为类型CMyString的声明,请为该类型添加赋值运算符函数
class CMyString
{
public:
CMyString(char * pData = NULL);
CMyString(const CMyString & str);
~CMyString(void);
private:
char * pData;
}
解决这个问题需要考虑几点:
1. 把返回值的类型声明为该类型的引用, 因为函数本身是不能作为左值的。所以如果返回类型设为void,应用该赋值运算符将不能做连续赋值,如 str1 = str2 = str3
2. 传入参数的类型声明为引用,这样可以避免形参到实参的一次拷贝,提高带代码的效率。
3. 记得释放实例本身占用的内存,否则会造成内存泄露
4. 记得判断传入的参数和当前实例不是同一个实例,如果是同一个,则不进行赋值操作,直接返回。
考虑到这几个问题,我们代码就出来了:
1 1 CMyString & CMyString::operator = (const CMyString & str) 2 2 { 3 3 if(*this == str) //当然类定义中要重载==。 而且关系运算符最好以友元函数的形式重载 4 4 return * str; 5 5 6 6 delete [] m_Ddata; 7 7 m_pData = NULL; //释放过后的内存指针要指向=NULL,防止产生野指针 8 8 m_ pData = new char[strlen(str.m_pData)+1]; //字符串默认最后会加上'\0'作为结束,所以要多申请1个空间 9 9 strcpy(m_pData, str); 10 10 11 11 }
写出这样的代码对于初级程序员来说就已经足够了,当然书中后面也给出了考虑异常安全性的解法, 这里就不列出了。
另外,书中前面还给出了个程序改错题,错误的原始是因为拷贝构造函数使用的传值操作,而不是传引用。 我们都知道传值操作会进行一次形参到实参的拷贝,拷贝的过程中会调用类的拷贝构造函数,这样就会造成永无休止的递归调用,直到栈溢出。