[C++11阅读][1-2-2]提高代码稳定性(上)
稳定性
我的补充
第二章的标题叫做“保持稳定性和兼容性”,兼容性在前面说过了,指的是兼容C标准。关于稳定性,我理解是指编写代码时不易出错,帮助养成好的编码习惯,类似const关键字起的作用。
如果不用这些特性,可以做到代码功能完整,甚至性能也不错。用了这些特征,防止日后编写代码时出错,防止其他人修改代码时出错,防止库的调用者出错。
断言与静态断言
运行时断言assert一直都有,C++11新增了静态断言宏static_assert。
都是判断为true时继续走,false时中止,static_assert可以加消息。
// 断言,运行时进行判断
assert(features.size() > 0);
// 静态断言,编译时进行判断
static_assert(sizeof(st) == sizeof(index), "recognifion feature should have same size for int64");
要持有这样的观念,断言是开发阶段debug用的,运行时要disable掉。编译宏NDEBUG可以起到release时使断言失效的效果,不要在代码里定义NDEBUG,用就行,这是编译选项做的。
#ifdef NDEBUG
/*
* If not debugging, assert does nothing.
*/
#define assert(x) ((void)0)
#else /* debugging enabled */
// some code
#endif /* NDEBUG */
noexcept修饰符与noexcept操作符
noexcept可以吃掉内部抛出的异常,外部代码就不用处理了,这样代码运行更可控一些。
吃掉的含义是如果真的发生异常了,就地中止,调用std::terminate()。
// finally() - convenience function to generate a final_action
template <class F>
inline final_action<F> finally(const F& f) noexcept
{
return final_action<F>(f);
}
noexcept还可以作为操作符,noexcept等同于noexcept(true),不抛异常,如果是noexcept(false)则为会抛出异常,后者比较少见。
作为修饰符的noexcept
https://zh.cppreference.com/w/cpp/language/noexcept_spec
作为操作符的noexcept
https://zh.cppreference.com/w/cpp/language/noexcept
就地初始化成员变量
#include <string>
using namespace std;
class Init {
public:
Init(): a(0){}
Init(int d): a(d){}
private:
int a;
const static int b = 0;
int c = 1; // 用double或char*效果一样,C++11可以,C++98/03不行
static int d = 0; // C++11无法通过编译
static const double e = 1.3; // 非整形或者枚举,C++11无法通过编译
static const char * const f = "e"; // 非整形或者枚举,C++11无法通过编译
};
int main() {
Init lala;
return 0;
}
用g++编译int c会报错(其实GNU处理成了warning),用g++ -std=c++11就没事。
细心的你会发现用g++时,double e那句没报错,是因为GNU对C++的扩展,并不是标准的。
image.png
初始化列表和就地初始化可以同时存在,同时存在时,起效的是构造函数的初始化列表。就地初始化在有多个构造函数时很有用,在其中有的构造函数没有初始化列表时起效。