01.视C++为一个语言联邦
- C
- Object-Oriented C++
- Template C++
- STL
过程形式(procedural),面向对象形式(object-oriented),函数形式(functional),泛型形式(generic),元编程形式(metaprogramming)
问题:
泛型形式和元编程形式的区别?
过程形式和函数形式的区别?
结论:
对于内置类型而言pass-by-value通常比pass-by-reference高效。
02.尽量以const,enum,inline替换#define
char * const 指针不可更改
const char* 指针指向内容不可更改
define存在的问题:
- 编译错误信息中无法展示宏名称,造成定位问题不够高效。define不会进入符号表。
- define变量未加括号引入问题。
- define替换变量使用++时引入问题。
#define CALL_WITH_MAX(a,b) f((a) > (b) ? (a) : (b))
CALL_WITH_MAX(++a,b); // a被累加两次,和预期不符
结论:
对于单纯常量,以const对象或enum替换define
对于类似函数形式的宏,以inline函数替换define
遗留问题:
enum的详细使用
03.尽量使用const
作用:
- 修饰global或namespace作用域中的常量
- 修饰文件,函数,区块作用域被声明为static的对象
- 修饰classes内部的static和no-static成员变量
- 修饰指针
char greeting[] = "hello"; char* p = greeting;// non-const pointer,no-const data const char* p = greeting;// non-const pointer,const data char* const p = greeting; // const pointer,non-const data const char* const p = greeting;// const pointer,const data const vector<int>::iterator itr;// const itr,no-const data vector<int>::const_iterator itr;// non-const itr,const data
函数返回constclass Rational {}; const Rational operator* (const Rational& lhs, const Rational& rhs); // 声明返回const为了避免执行如下操作 Rational a,b,c; (a*b) = c; // 避免执行如下无意义的操作 if (a*b = c)
遗留问题:提领操作符重载的格式(参数格式和乘法操作符格式不同)
new操作符重载
const 成员函数
class TextBlock { char& operator[] (size_t position) const { return text[position]; } // for const对象 char& operator[] (size_t position) { return text[position]; } // for no-const对象 string text; } TextBlock tb; tb[0]; // 调用no-const TextBlock::operator[] const TextBlock ctb; ctb[0]; // 调用const TextBlock::operator[]
如果operator[] 返回char,tb[0] = 'x'无法编译通过,因为如果函数类型是内置类型,那么改动函数返回值不合法。
mutable,释放掉non-static成员变量的bitwise constness约束,const成员函数可以修改成员变量。
在const和non-const成员函数中避免重复:
- 提取公共函数
- 有non-const函数调用const函数
遗留问题:c++四种转换class TextBlock { const char* operator[] (size_t position) const {} char* operator[] (size_t position) { return const_cast<char&>( static_cast<const TextBlock&>(*this)[position] ); } }
04.确定对象被使用前已先被初始化
问题:
类中内置数据类型是否会被初始化?(不会被初始化)
结论:
成员变量按照声明的顺序进行初始化。
全局静态对象通过在函数中使用local static来代替,解决依赖初始化顺序的问题。