天天看点

Effective C++ -- 让自己习惯C++

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
           
函数返回const
class 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函数
class TextBlock {

const char* operator[] (size_t position) const {}

char* operator[] (size_t position) { return const_cast<char&>( static_cast<const TextBlock&>(*this)[position] ); }

}
           
遗留问题:c++四种转换

04.确定对象被使用前已先被初始化

问题:

类中内置数据类型是否会被初始化?(不会被初始化)

结论:

成员变量按照声明的顺序进行初始化。

全局静态对象通过在函数中使用local static来代替,解决依赖初始化顺序的问题。

继续阅读