天天看點

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來代替,解決依賴初始化順序的問題。

繼續閱讀