C++面试题评分:strcpy和String类的书写
关于C++的面试方面,林锐博土的<<高质量C++/C编程指南>>里附带的一些试题被大量引证来测试应试人员的基础。很不幸,我也被做了一份,回来后,和林锐的标准答案一对,觉得,他的答案还是有些不足之处,下面我就说说那两个题,也许凭记忆能回忆起面试中的一些趣事。1.已知strcpy函数的原型是 char *strcpy(char *strDest, const char *strSrc); 其中strDest是目的字符串,strSrc是源字符串。不调用C++/C的字符串库函数,请编写函数 strcpy林锐的标准答案如下:char *strcpy(char *strDest, const char *strSrc);{ assert((strDest!=NULL) && (strSrc !=NULL)); // 2分 char *address = strDest; // 2分 while( (*strDest++ = * strSrc++) != ‘\0’ ) // 2分 NULL ; return address ; // 2分}我在写时,写出下面这样子的:char *strcpy_x(char *strDest, const char *strSrc){ if((strDest==NULL) || (strSrc ==NULL)) return NULL; // 2分 if(strDest==strSrc)//add by xie return strDest; char *address = strDest; // 2分 while( (*strDest++ = * strSrc++) != '\0' ) // 2分 ; return address ; // 2分}我当时这样写的理由如下:a. 没必要为一个strcpy函数中的参数有NULL就断言大错涌出,返回NULL值也是一个好见识b. 为了防止写出strcpy(strDest,strSrc)(而strDest是等于strSrc,又很不凑巧strDest是大字串,这些代码又运行一种比较计时的环境下,所以判断是否相同应该是必须的。更重要的一点:林锐的这篇文章影响了好多公司招人,这样一写,我给别人留下的印象是不同的,你认为呢?:) 2. 相信大部人都看过甚至做过下面这个题:已知类String的原型为: class String { public: String(const char *str = NULL);// 普通构造函数 String(const String &other); // 拷贝构造函数 ~ String(void); // 析构函数 String & operate =(const String &other); // 赋值函数 private: char *m_data; // 用于保存字符串 }; 请编写String的上述4个函数。在我给出我找碴的理由先,我先给出林锐的标准答案及指出一点不足处:// String的析构函数 String::~String(void) // 3分{ delete [] m_data; // 由于m_data是内部数据类型,也可以写成 delete m_data; } // String的普通构造函数 **** Hidden Message *****// (4)返回本对象的引用 // 3分 return *this;} 哈哈,第一个吐槽很好哇,第二个我没看明白你这是改之前的还是之后的,我来批判一下吧,主要以下两点:
首先,使用delete代替delete[]删除char数组显然是不好的,虽然在一些体系结构上,对于char*类型可能不至于内存泄漏。但是某一天这里改成了其它类型呢?或者某某QA用valgrind跑了一把你写的程序呢?作为Developer收到这种Bug不觉得烦躁么?我试了一下,报告如下:
==9653== Mismatched free() / delete / delete []
==9653== at 0x402ACFC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==9653== by 0x804861D: main (in /home/extli/a.out)
==9653==Address 0x4320028 is 0 bytes inside a block of size 8 alloc'd
==9653== at 0x402B454: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==9653== by 0x80485E8: main (in /home/extli/a.out)
==9653==
==9653== HEAP SUMMARY:
==9653== in use at exit: 0 bytes in 0 blocks
==9653== total heap usage: 1 allocs, 1 frees, 8 bytes allocated
==9653==
==9653== All heap blocks were freed -- no leaks are possible
==9653==
==9653== For counts of detected and suppressed errors, rerun with: -v
==9653== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
其次,添加空指针判断没有必要,即便源字符串中m_data为NULL,取源对象属性以及动态内存分配都得有,唯一多的就是strlen和strcpy两个函数调用,但这里处理一个字节的'\0'可以认为几乎不多耗时间。况且已经普适的代码拉分支是不好的,根据《More Effective C++》的讨论,这里提高代码效率的办法应该是对构造方法使用初始化列表。因为属性的最终值计算并不复杂,应采纳建议放在初始化列表中。而且初始化列表会使得代码在易读性上提高很多,有多层继承关系类的对象构造过程清晰可见。一个例子:
String(const char *str) : m_data(new char) {
strcpy(m_data, str);
}
必看。。学习 不错 学习了。。。。。。。。。。 学习了,喜欢string讨厌char *啊。。。 学习学习{:5_134:} 学习了,多谢学长 学习学习。。。 来膜拜的。现身吧! 很不错,学习了 曾经被这道面试题坑了 先回帖仔细看看 技术贴,必须要顶{:9_414:} 1024!1024! 这几题确实很常考 顶!!! 技术贴,顶顶、、、、 欧?还有这种面试? 不错,科普一下 看看
凑够十个字,十个字 先回帖,,再看内容 {:5_156:}dddd {:5_134:}先回帖再看 很好很受益 先回贴!。。。
页:
[1]