关于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的普通构造函数 游客,如果您要查看本帖隐藏内容请回复 // (4)返回本对象的引用 // 3分 return *this; } |
[技术| 编程·课件·Linux] C++面试题评分:strcpy和String类的书写
service
· 发布于 2012-11-13 23:12
· 2939 次阅读
转载文章时务必注明原作者及原始链接,并注明「发表于 软院网 RuanYuan.Net 」,并不得对作品进行修改。
哈哈,第一个吐槽很好哇,第二个我没看明白你这是改之前的还是之后的,我来批判一下吧,主要以下两点: 首先,使用delete代替delete[]删除char数组显然是不好的,虽然在一些体系结构上,对于char*类型可能不至于内存泄漏。但是某一天这里改成了其它类型呢?或者某某QA用valgrind跑了一把你写的程序呢?作为Developer收到这种Bug不觉得烦躁么?我试了一下,报告如下: [Plain Text] 纯文本查看 复制代码 ==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++》的讨论,这里提高代码效率的办法应该是对构造方法使用初始化列表。因为属性的最终值计算并不复杂,应采纳建议放在初始化列表中。而且初始化列表会使得代码在易读性上提高很多,有多层继承关系类的对象构造过程清晰可见。一个例子: [C++] 纯文本查看 复制代码 String(const char *str) : m_data(new char[strlen(str)+1]) { strcpy(m_data, str); } |
评分
很不错,学习了 |
技术贴,必须要顶 |
这几题确实很常考 |
不错,科普一下 |
dddd |
先回帖再看 |