• C++是一個語言聯邦(Federation of languages)函數
1. C Style languagethis
2. Object-Oriented C++spa
3. Template C++指針
4. STL/TR1/boost..代碼規範
• 使用const,enum,inline代替#definecode
1. 使用const datatype constName = constValue 代替 #define constName constValue對象
好比全局常量:blog
const int maxN = 1000005; //代替 #define maxN 1000005
在類中,類專屬常量:編譯器
class someClass{ private: static const int maxN = 1000005; int someData[maxN]; ... }
2. enum hack!string
class someClass{ private: enum { maxN = 1000005 };//enum令maxN變成一個記號名稱 int someData[maxN]; ... }
enum的某些特性更像#define而不是const,某些狀況下更符合咱們的需求。(例如取地址對於enum不合法而對const就合法)
enum hack使template metaproprogramming的基礎技術。
3. 使用inline function代替宏
常見宏 #define call_with_max(a, b) foo(a > b ? a : b) 會出現大量的錯誤,
必須使用小括號將參數所有區別 #define call_with_max(a, b) foo((a) > (b) ? (a) : (b)) ,
即使如此在實際操做時依舊容易出錯(不能擴展代碼與靈活調用),應用inline function取代
template <typename T> inline void callWithMax(const T& a, const T& b){ foo(a > b ? a : b); }
• Const的妙用
1. Const聲明幫助編譯器偵測出錯誤
const指定了一個不可改動的對象,而編譯器會強制的實施它。(!指出來能夠得到編譯器的幫助,確保其不被違反!)
這個對象能夠是global或者namespace域中的常量。也能夠修飾block scope中被聲明爲static的對象,亦能夠修飾class內部的全部變量。
而對於指針,能夠指出指針自身,指針所指,二者皆是,或二者皆不是Const。在*左表示指針所指是常量,在*右表示指針自身是常量,而在*兩側表示二者皆是常量。
int someValue = 12345; int* pSomeValue = someValue; // 二者皆不是常量 const int* pSomeValue = someValue // 所指爲常量 int* const pSomeValue = someValue // 指針爲常量 const int* const pSomeValue = someValue // 二者皆是常量
void foo(const dataType* arg) // 傳入一個指向常量的指針 void foo(dataType const* arg) // 與上面相同 在*左次序顛倒沒有區別
迭代器也是指針衍生出來的,因此
std::vector<int> vec; ... const std::vector<int>::iterator iter = vec.begin(); // 迭代器的做用就像一個 T* const (模板變量的常量指針) *iter = 12345; // ok! 指針所指不是常量 ++iter; // error! 指針自己是常量 std::vector<int>::const_iterator cIter = vec.begin(); // cIter的做用如同一個 const T* (模板常量的變量指針) *cIter = 12345; // error! 指針所指是常量 ++cIter; // ok! 指針自己不是常量
將const應用於函數聲明
良定義的數據類型應儘可能避免隱式類型轉換,這時返回一個常量值就十分有用
class Rational {...}; const Rational operator+ (const Rational& lhs, const Rational rhs); const Rational operator* (const Rational& lhs, const Rational rhs); ...
這樣定義, if(a * b = c) // 本意是想作一個if(a * b == c)的比較 這樣的錯誤就不會出現,而會被編譯器直接警告。
2. const成員函數
使用const來控制成員函數對對象的可讀寫性是很重要的,由於這樣可使class藉口更容易被理解,而且還可使操做const對象成爲可能。這對高效編寫代碼很重要。
class SomeText { public: ... const char& operator[](std::size_t position) const { return text[position]; } char& operator[](std::size_t position) { return text[position]; } } SomeText text("Hello,world!"); std::cout << text[0]; // 調用non-const方法 能夠讀 text[0] = 'A'; // 調用non-const方法 能夠寫 const SomeText cText("Hello,world!"); std::cout << cText[0]; // 調用const方法 能夠讀 cText[0] = 'A'; // 調用const方法 不可寫!
對於在const中也想改變的量,使用mutable能夠聲明在const成員函數內依舊可被更改的變量。
若是成員函數代碼功能相同而只有常量變量的區別,能夠const_cast,static_cast來避免代碼重複。
class SomeText { public: ... const char& operator[](std::size_t position) const { ... ... ... return text[position]; } char& operator[](std::size_t position) { return const_cast<char&> // 移除返回值的const (static_cast<const SomeText&> // 爲*this加上const (*this)[position]); // 調用const op[] }
• 變量與對象的初始化與代碼規範
1. 代碼規範:
類型 | 規範 | 示例 |
簡單數據類型 | 首字母小寫表示類型,以後按單詞分割每單詞首字母大寫。 |
int iMaxNum = 10000; char cRank = 'A'; string sName = "LevisonChen"; double dSpeed = 1.357; int* pMaxNum = iMaxNum; |
複雜數據類型 | 首字母小寫,首詞表示數據類型,以後按單詞分割每單詞首字母大寫 |
std::vector<int> vecEdges;
|
函數 | 按單詞分割每單詞首字母大寫 |
void Foo(){ ... } int GetMaxinum(std::vector<int> vecArg){ ... } |
類與結構體 | 按單詞分割每單詞首字母大寫,私有字段不使用首詞表示數據類型 |
class SomeClass { ... } struct SomeStruct { ... } |
縮進 | tab-4spaces縮進 |
{
...
{
...
{
...
...
...
}
...
}
...
}
|
2. 不要混淆賦值(assignment)和初始化(initialization)
class Person { public: Person(const std::string& sName, const std::int& iAge, const std::list<PhoneNumber>& listPhones, const std::list<EmailAddress>& listEmails); private: std::string name; std::int age; std::list<PhoneNumber> phones; std::list<EmailAddress> emails; }; Person::Person(const std::string& sName, const std::int& iAge, const std::list<PhoneNumber>& listPhones, const std::list<EmailAddress>& listEmails) { name = sName; age = iAge; phones = listPhones; emails = listEmails; } // 這是賦值而非初始化!
Person::Person(const std::string& sName, const std::int& iAge, const std::list<PhoneNumber>& listPhones, const std::list<EmailAddress>& listEmails) :name(sName), age(iAge), phones(listPhones), emails(listEmails) // 這是初始化! {}
爲了消除跨編譯時的單元初始化次序問題,應以local static對象替換non-local static對象。