转向现代C++的一些惯用法
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
多种多样的初始化形式
- 初始化物在小括号内
int x(0)
a. - 初始化物在等号之后
int x(0)
- 初始化物在大括号内
int x{0}
a. 应用场景广
b. 禁止内建类型之间的隐式窄化类型转换
c. 免疫C++令人苦恼的解析语法int x() 被解析为函数声明
d. 缺陷在于伴随大括号初始化物、std::initializer_list以及构造函数重载决议之间的纠结关系
e. 在构造函数被调用时只要所有的构造函数中都没有带std::initializer_list的形参那么小括号和大括号没有区别
f. 在构造函数被调用时如果有一个及以上构造函数具有std::initializer_list型别的形参那么采用大括号初始化语法的调用语句会强烈优先选用带有std::initializer_list形参的重载版本 - 同时使用等号和大括号
int x={0}
a. 效果同3
优先选择nullptr而非0或者NULL
- nullptr是一个真正的通用类型指针而不是0或者void*(0)之类的东西
- nullptr不会产生重载决议问题
- 可以提高程序可读性
- 涉及到模板时0或者NULL可能推导出错误的类型而nullptr不会
优先选择using声明而非typedef
- using声明要更好理解
- using声明对模板更加友好
- using声明可以让人避免写"::type"后缀并且在模板内对于内嵌typedef的引用经常要求加上typename前缀
优先选择限定作用域的枚举类型而非不限定作用域的枚举类型
- 限定作用域的枚举类型可以降低名字空间污染的可能性
- 限定作用域的枚举类型时强类型的不可以隐式转换到整形可以强制类型转换到整形
- 一切枚举类型在C++中都会由编译器来选择一个整数类型作为其底层类型
- 枚举类型在C++98中会增加编译依赖性原因无法进行前置声明根本原因是编译器为了进行空间优化。
- 为什么C++11中的枚举类型可以进行前置声明而C++98中不行呢在C++11中限定作用域的枚举类型和不限定作用域的枚举类型都支持底层类型指定限定作用域的枚举类型的底层类型是已知的默认为int而对于不限范围的枚举类型没有默认的底层类型因此如果你想前置声明不限作用域的枚举类型必须指定其底层类型
- 不限定作用域的枚举类型在需要与整形进行隐式类型转换的场景还是有一席之地的使用限定作用域的枚举虽然能获得以上优点但是写法相对繁琐
- 限定作用域的枚举类型总是可以进行前置声明而不限范围的枚举类型却只有在指定了默认底层类型的前提下才可以进行前置声明。
优先选择删除函数而非私有未定义函数
- 删除函数无法通过任何方法调用而私有未定义的方式在友元以及成员函数的调用情况下 将会推迟到链接阶段才能报错。
- 声明删除函数时在public作用域下能够得到更加清晰地诊断信息
- 删除函数可以阻止不应该进行的模板具现
- 任何函数都能成为删除函数但只有成员函数可以使用私有未定义的方式
为意在改写的函数添加override声明
- 成员函数的引用饰词使得对左值和右值对象的处理能够区分开来即引用饰词也是函数重载的一个条件
函数重写条件
- 基类中的函数必须是虚函数
- 基类和派生类中的函数名一致析构除外
- 基类和派生类中函数的形参一致
- 基类和派生类中函数常量性一致
- 基类和派生类中的函数返回值和异常规格必须兼容
- 基类和派生类的函数引用饰词一致C++11
优先选择const_iterator而非iterator
只要函数不会发射异常就为其加上noexcept声明
- noexcept声明是函数接口的组成部分这意味着调用方可能对它有依赖
- 相对于不带noexcept声明的函数带有noexcept声明的函数有更多的机会得到优化
- 带有noexcept的函数有可能会将复制操作改为移动操作
- noexcept性质对于移动操作、swap、内存释放函数和析构函数最有价值
- 大多数函数都是异常中立的不具备noexcept性质
- 一个函数是否抛出异常远比该函数抛出的是什么异常要重要的多因此C++98的异常规格虽然依旧能够使用但已经成为废弃特性了。在C++11中noexcept就是为不会发射异常的函数准备的
- 函数是否加上noexcept声明试管接口设计。如果你明明知道一个函数不会发射异常却没有给他加上noexcept声明的话这就是接口缺陷
- 在C++11中默认内存释放函数和所有析构函数都具备noexcept性质
只要有可能使用constexpr就使用它
- constexpr对象都具备const属性由编译期已知的值完成初始化在编译器可以确定。被放置在只读内存中可以被使用在C++中要求常量表达式的位置。
- const对象并未提供和constexpr一样的保证因为const对象不一定经由编译期已知的值来初始化。
- 所有的constexpr对象都是const对象但是并非所有的const对象都是constexpr对象。如果你想让编译器提供保证让变量拥有一个值用于要求编译期常量的语境那么能达到这个目的的工具就是constexpr而非const
- constexpr函数不一定是const的并且其值不一定在编译期已知。
- constexpr函数可以用在要求编译期常量的语境中在这样的语境中若你传给一个constexpr函数的实参是在编译期已知的则结果也会在编译期间计算出来如果任何一个实参在编译期未知则你的代码将无法通过编译。
- 在调用constexpr函数时若传入的实参有一个或多个在编译期未知则他的运作方式和普通函数没有区别即在运行期得到计算结果
- constexpr在C++11中函数体不能多于一条可执行语句在C++14中可以有多条
- constexpr函数仅限于传入和返回字面类型即这样的类型能够持有编译期可以决议的值。在C++11中所有内建类型除了void都符合这个条件但用户自定义类型同样可能也是字面类型。在C++11中constexpr函数都隐式地被声明为const的了并且返回值不能是void这两个限制在C++14中都被解除了
- 比起非constexpr对象或函数constexpr对象和函数的使用场景更加广泛并且可以提高运行效率
10.constexpr作为对象和函数接口声明的一部分必须保证其长期有效性
保证const成员函数的线程安全性
- 保证const成员函数的线程安全性除非可以保证他们不会用在并发语境下
- 运用std::atomic变量往往比使用互斥量要有更好的性能但是适用范围减小了因此如果可以使用std::atomic替换到互斥锁那么就应该立刻行动
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |