不要包含不必要的頭文件
盡量使用前向聲明的方式,目的是為了減少編譯時間What are forward declarations in C++?,并且在頭文件發(fā)生改變的時候,減少重新編譯的文件。
將內(nèi)部類移動到實現(xiàn)中
// 內(nèi)部類的聲明class Whatever { public: /* ... */ PRivate: struct DataStruct; std::vector<DataStruct> data_;};struct Whatever::DataStruct {};某些時候你不能這么做,因為某些STL數(shù)據(jù)結(jié)構(gòu),需要在聲明的時候就知道其定義,比如:std::deque
? 不使用這個接口的人是不需要關(guān)心BigImplementationDetail
實現(xiàn)細節(jié)的。使用匿名空間的好處就是可以限制對象的作用域在本文件中。
停止對虛方法進行內(nèi)聯(lián)
? 在大多數(shù)情況不要對一個虛方法進行內(nèi)聯(lián),即使是因為這些方法很短也是不可以的,編譯器必須在運行時根據(jù)虛函數(shù)表和指向的類型做分發(fā),如果內(nèi)聯(lián)了就無法知道指向的類型。
Can virtual functions be inlined?
Are inline virtual functions really a non-sense?
?
停止內(nèi)聯(lián)構(gòu)造和析構(gòu)函數(shù)
? 構(gòu)造函數(shù)和析構(gòu)函數(shù)要比我們想象中的要復(fù)雜,因為編譯器會幫我們插入很多初始化的代碼,因此不要認為構(gòu)造函數(shù)和析構(gòu)函數(shù)中沒寫代碼就可以內(nèi)聯(lián)。
什么情況下可以有構(gòu)造函數(shù)和析構(gòu)函數(shù)
如果你的類只有POD類型的數(shù)據(jù),并且沒有顯示的聲明析構(gòu)函數(shù),那么編譯器也不會生成trivial destructor。
struct Data { Data() : count_one(0), count_two(0) {} // No explicit destructor, thus no implicit destructor either. // The members must all be POD for this trick to work. int count_one; int count_two;};? 沒有繼承,只有很少一些POD類型,構(gòu)造函數(shù)都是一些trivial的整型操作,所以是可以內(nèi)聯(lián)的。對于抽象類, 并且沒有成員的情況,它是可以安全內(nèi)聯(lián)一個trivial的析構(gòu)函數(shù)
class Interface { public: virtual ~Interface() {} virtual void DoSomething(int parameter) = 0; virtual int GetAValue() = 0; };? 下面兩個接口,不能進行inline。
class ClaimsToBeAnInterface : public base:RefCounted<ClaimsToBeAnInterface> { public: virtual ~ClaimsToBeAnInterface() { /* But derives from a template! */ }};class HasARealMember { public: virtual void InterfaceMethod() = 0; virtual ~HasARealMember() {} protected: vector<string> some_data_;};小心你的訪問器
不是所有的訪問器都是輕量級的
class Foo { public: int count() const { return count_; } private: int count_;};? 上面這個訪問器是trivial的,可以很安全的inline,但是下面這些代碼就不行了,即使它們看起來很像。
struct MyData { vector<GURL> urls_; base::Time last_access_;};class Manager { public: MyData get_data() { return my_data_; } private: MyData my_data_;};? MyData底層的數(shù)據(jù)拷貝很復(fù)雜,所以不適合inline
? TODO
? 動態(tài)初始化函數(shù)作用域內(nèi)的靜態(tài)變量在C++11
中是線程安全的,因此base::LazyInstance
被廣泛使用,
在C++11中有很多方式可以用來初始化一個變量,優(yōu)先遵從下面這些規(guī)則:
對于簡單變量的初始化,以及多個literal value組成一個對象的初始化使用賦值語法int i = 1;std::string s = "Hello";std::pair<bool, double> p = {true, 2.0};std::vector<std::string> v = {"one", "two", "three"};這里使用=
號并不會沒有()
效率高,因為這里編譯器不會生成臨時變量進行拷貝,并且確保只有隱式的構(gòu)造函數(shù)被調(diào)用,因此讀者在看到這種調(diào)用方式可以假設(shè)沒有什么復(fù)雜或微妙的事情發(fā)生。
? base::MakeUnique(…) 和 base::WrapeUnique(new Type())是等同的,MakeUnique更好,因為通常來說用它很難寫出不安全的代碼。
return std::unique_ptr<C>(new C(1, 2, 3)); // BAD: type name mentioned twice return base::WrapUnique(new C(1, 2, 3)); // BAD: bare call to new return base::MakeUnique<C>(1, 2, 3); // GOOD注意: MakeUnique就是C++14中的make_unique的實現(xiàn)
不要將MakeUnique設(shè)置為類的友元,因為這會讓任何人都可以構(gòu)造這個類 class Bad { public: std::unique_ptr<Bad> Create() { return base::MakeUnique<Bad>(); } // ... private: Bad(); // ... friend std::unique_ptr<Bad> base::MakeUnique<Bad>(); // Lost access control};class Okay { public: // For explanatory purposes. If Create() adds no value, it is better just // to have a public constructor instead. std::unique_ptr<Okay> Create() { return base::WrapUnique(new Okay()); } // ... private: Okay(); // ...}; 對于WrapUnique(new Foo) 和 WrapUnique(new Foo()) 來說,如果Foo沒有自定義的構(gòu)造函數(shù)的話那么這兩者的含義是不同的,不要讓未來的維護者猜測你是否是故意不寫(),使用MakeUnique()來替換,如果你是有意不寫()來作為優(yōu)化,請加上說明 auto a = base::WrapUnique(new A); // BAD: "()" omitted intentionally? auto a = base::MakeUnique<A>(); // GOOD // "()" intentionally omitted to avoid unnecessary zero-initialisation. // WrapUnique() does the wrong thing for array pointers. auto array = std::unique_ptr<A[]>(new A[size]);? 鼓勵使用auto來從初始化表達式中進行類型推導(dǎo),但是當推導(dǎo)的是指針類型的時候不要使用auto,這會給使用者帶來疑惑,應(yīng)該使用auto*來替代,如下:
auto item = new Item(); // BAD: auto deduces to Item*, type of |item| is Item*auto* item = new Item(); // GOOD: auto deduces to Item, type of |item| is Item*新聞熱點
疑難解答
圖片精選