参考的Andrey Karpov的<<C++编程的 42 条建议>>
这里可能有一些老古董的东西,仅供参考
11.单是文件终止符(EOF)的检查还不够。
有时候‘cin.eof()’这个条件不够。考虑加‘cin.fail()’这一函数调用到条件表达式中。
template <typename T>
std::istream &operator >>(std::istream &i, sqlblob<T> &b)
{
....
while (!i.eof())
{
i >> tmp;
buf+=(tmp+' ');
}
....
}
解释:用eof()来检查文件结束不是充分条件,而且你无法确定是否出现了读取错误或者流出错,这两个都会引起特定的问题。如果有任何数据读取错误,就会导致无限循环,因为eof()总返回 false。这个在循环种可能会造成死循环。所以我们要用bad(), fail()来查询流状态。
建议:当用流来读取数据的时候,不要只使用 eof(),还要检查其他故障。 使用 bad() 和 fail()函数来检查流的状态。第一个函数是用来流的完整性,第二个函数是用来检查数据读取错误的。但是,用 bool()操作会更便捷一些,就像在正确代码那里显示的。
例子:
template <typename T>
std::istream &operator >>(std::istream &i, sqlblob<T> &b)
{
....
while (i >> tmp)
{
buf+=(tmp+' ');
}
....
}
12.自动计算字符串长度。
例如:
else if (!strncmp(vstart, "HEX", 3))
之后,用"BITLIST"代替"HEX" ,但是程序员忘了把 3 改为 7. 结果就是,字符串不是和"BITLIST"做比较,而是仅仅比较了"BIT"。这个错误似乎不太严重,但终究是个错误。
修改:
else if (!strncmp(vstart, "BITLIST", strlen("BITLIST")))
用strlen(“BITLIST”)会比较好
但这样是有缺点的:
- 无法保证编译器会不会优化 strlen()调用:用一个常数来代替它。
- 你要逐字复制字符串。看上去不好看,而且也会出错。
在C++中我们可以用模板,我个人不喜欢用宏:
template<typename T, size_t N>
int mystrncmp(const T *a, const T (&b)[N])
{
return _tcsnccmp(a, b, N - 1);
}
13.学会使用Override 和 final 标识符。
用了这两个标识符,对重写函数有帮助。
- Override——表明该函数是重写基类中的虚函数。
- Final——表明该函数在派生类中无需重写。
例子:
class CFrameWndEx : public CFrameWnd {
....
virtual void WinHelp(DWORD_PTR dwData,
UINT nCmd = HELP_CONTEXT) override;
....
};
14.不要再拿‘this’和 nullptr 比较。
根据现代 C++标准,this 永远不会等于 nullptr。