More Effective C++ (运算符)
4.1:謹慎定義類型轉(zhuǎn)換函數(shù)
<1>容易的方法是利用一個最新的編譯器特性:explicit關(guān)鍵字
<2>C++編譯器把">>"作為一個符號來解釋,在兩個">"間沒有空格,語句會產(chǎn)生語法錯誤。
<3>隱式類型轉(zhuǎn)換函數(shù)
示例代碼如下:
1 #include<iostream> 2 using namespace std; 3 4 template<class T> 5 class Array 6 { 7 public: 8 class ArraySize 9 { 10 public: 11 ArraySize(int numElements):theSize(numElements) 12 { 13 cout<<"flag ArraySize(int numElements)"<<endl; 14 } 15 int size() const 16 { 17 cout<<"flag size()"<<endl; 18 return theSize; 19 } 20 private: 21 int theSize; 22 }; 23 24 Array(int lowBound,int highBound) 25 {}; 26 27 Array(ArraySize arsize) 28 { 29 cout<<"flag Array"<<endl; 30 }; 31 }; 32 void main() 33 { 34 Array<int> a(10); 35 } 36 37 /* 38 flag ArraySize(int numElements) 39 flag Array 40 */4.2:自增,自減操作符前綴形式和后綴形式
<1>重載函數(shù)間的區(qū)別決定于它們的參數(shù)類型上的差異,但是不論increament或者decrement的前綴還是后綴都只有一個參數(shù)。
為了解決這個語言問題,C++規(guī)定后綴形式有一個int類型參數(shù),當函數(shù)被調(diào)用時,編譯器傳遞一個0作為int參數(shù)的值給該函數(shù)。
<2>前綴自增:增加然后取回;后綴自增:取回然后增加
<3>前綴形式
示例代碼如下:
1 UPInt & UPInt::operator++() 2 { 3 *this += 1; //增加 4 return *this; //取回值 5 } 6 const UPInt UPInt::operator++(int) 7 { 8 UPInt oldValue = *this; //保留原值 9 ++(*this); //增加 10 return oldValue; //返回原值 11 }<4>后綴操作符函數(shù)沒有使用它的參數(shù)。這個參數(shù)僅僅只是為了區(qū)別前綴函數(shù)調(diào)用。
<5>如果在函數(shù)內(nèi)部沒有使用參數(shù),許多編譯器會顯示警告信息。為了避免這些信息,最常用的方式就是省略掉參數(shù)名稱
<6>很明顯后綴函數(shù)必須返回一個對象,但是為什么是const對象呢?假設(shè)不是const:
假設(shè)不是 const 對象,下面的代碼就是正確的:
這組代碼與下面的代碼相同:?
i.operator++(0).operator++(0); ?
很明顯, 第一個調(diào)用的operator++函數(shù)返回的對象調(diào)用了第二個operator++函數(shù)。 有兩個理由導(dǎo)致我們應(yīng)該厭惡上述這種做法:
第一,是與內(nèi)置類型行為不一致。當設(shè)計一個類遇到問題時,一個好的準則是使該類的行為與int 類型一致。而int 類型不允許連續(xù)進行兩次后綴 increment:?
int i;?
i++++; // 錯誤!?
第二個原因,是使用兩次后綴 increment 所產(chǎn)生的結(jié)果與調(diào)用者期望的不一致。
如上所示,第二次調(diào)用operator++改變的值是第一次調(diào)用返回對象的值,而不是原始對象的值。因此如果:
i++++; 是合法的,i 將僅僅增加了一次。這與人的直覺相違背,使人迷惑(對于int類型和 UPInt 都是一樣),所以最好禁止這么做。
C++禁止int 類型這么做,同時你也必須禁止你自己寫的類有這樣的行為。
最容易的方法是讓后綴 increment 返回 const 對象。當編譯器遇到這樣的代碼: ?
i++++; // same as ?
i.operator++(0).operator++(0);
它發(fā)現(xiàn)從第一個 operator++函數(shù)返回的 const 對象又調(diào)用 operator++函數(shù),然而這個函數(shù)是一個 non-const 成員函數(shù), 所以 const 對象不能調(diào)用這個函數(shù)。
如果你原來想過讓一個函數(shù)返回 const 對象沒有任何意義,現(xiàn)在你就知道有時還是有用的,后綴 increment和 decrement 就是例子。 (更多的例子參見 Effective C++ 條款 21)?
如果你很關(guān)心效率問題, 當你第一次看到后綴 increment函數(shù)時,你可能覺得有些問題。
這個函數(shù)必須建立一個臨時對象以做為它的返回值, (參見條款M19) ,上述實現(xiàn)代碼建立了一個顯式的臨時對象(oldValue) ,這個臨時對象必須被構(gòu)造并在最后被析構(gòu)。前綴 increment 函數(shù)沒有這樣的臨時對象。
由此得出一個令人驚訝的結(jié)論,如果僅為了提高代碼效率,UPInt 的調(diào)用者應(yīng)該盡量使用前綴 increment,少用后綴 increment,除非確實需要使用后綴 increment。
讓我們明確一下,當處理用戶定義的類型時,盡可能地使用前綴 increment,因為它的效率較高。
我們再觀察一下后綴與前綴 increment 操作符。它們除了返回值不同外,所完成的功能是一樣的,即值加一。
簡而言之,它們被認為功能一樣。那么你如何確保后綴increment和前綴increment的行為一致呢?
當不同的程序員去維護和升級代碼時,有什么能保證它們不會產(chǎn)生差異?除非你遵守上述代碼里的原則,這才能得到確保。
這個原則是后綴 increment和 decrement 應(yīng)該根據(jù)它們的前綴形式來實現(xiàn)。你僅僅需要維護前綴版本,因為后綴形式自動與前綴形式的行為一致。
正如你所看到的,掌握前綴和后綴 increment和decrement 是容易的。
一旦了解了他們正確的返回值類型以及后綴操作符應(yīng)該以前綴操作符為基礎(chǔ)來實現(xiàn)的規(guī)則,就足夠了。
4.3:不要重載“&&”,“||”,或“,”
<1>char *p; if((p!=0)&&(strlen(p)>10))......
注意這個if條件的寫法順序
<2>運算符重載要求:
4.4:理解各種不同含義的new和delete
<1>new operator 稱為new操作符與operator new稱為new操作
string *ps = new string("Memory Management");
使用的是new operator ,即就是new操作符,這種用法是不可改變的,功能總是相同的。
完成兩部分任務(wù):第一,分配足夠的內(nèi)存以便容納所需類型的對象;第二,它調(diào)用構(gòu)造函數(shù)初始化內(nèi)存中的對象。
而我們所能改變的是如何為對象分配內(nèi)存。
new操作符調(diào)用一個函數(shù)來完成必需的內(nèi)存分配,你能夠重寫或重載這個函數(shù)來改變它的行為。
new操作符為分配內(nèi)存所調(diào)用函數(shù)的名字是 operator new。
原型如下:
void * operator new(size_t size);
調(diào)用形式與其他函數(shù)一樣:
void *rawMemory=operator new(sizeof(string));
placement new旨在完成一種情況,那就是假如我們已經(jīng)申請到了內(nèi)存,想要在該內(nèi)存上構(gòu)建對象,就選擇placement new
三種情況代碼如下:
1 #include<iostream> 2 using namespace std; 3 4 class Test 5 { 6 int a; 7 public: 8 Test(int data = 10):a(data) 9 { 10 cout<<"Construction :"<<this<<endl; 11 } 12 ~Test() 13 { 14 cout<<"Destroy :"<<this<<endl; 15 }; 16 }; 17 void main() 18 { 19 //new操作符(new operator) 20 Test *pa = new Test[2]; //完成兩部分任務(wù) 21 delete []pa; 22 pa = NULL; 23 24 //new函數(shù)(operator new) 25 void *pb = operator new(sizeof(Test)); //僅僅只是分配一塊內(nèi)存,類似于malloc 26 operator delete(pb); 27 pb = NULL; 28 29 //placement new 30 void *suffer = malloc(sizeof(Test)); 31 Test *pc = new(suffer) Test(100); //在已經(jīng)申請的內(nèi)存上建立自己的對象 32 pc->~Test(); 33 free(suffer); 34 suffer = NULL; 35 }總結(jié):
如果想在堆上創(chuàng)建一個對象,應(yīng)該用new操作符,它分配內(nèi)存,同時又為對象調(diào)用構(gòu)造函數(shù)。
如果僅僅想分配內(nèi)存,就用operator new函數(shù),它不會調(diào)用構(gòu)造函數(shù)
如果你想定制自己的在堆對象被建立時的內(nèi)存分配過程,應(yīng)該重載寫你自己的operator new函數(shù),new操作符會調(diào)用你定制的operator new
如果想在一塊已經(jīng)分配好的內(nèi)存里建立一個對象,使用placement new
<2>delete操作符與operator delete的關(guān)系與new操作符與operator new的關(guān)系一樣
delete p;
導(dǎo)致編譯器生成類似的代碼:
p->~Class();
operator delete(p);
?
轉(zhuǎn)載于:https://www.cnblogs.com/Braveliu/archive/2013/01/06/2847167.html
總結(jié)
以上是生活随笔為你收集整理的More Effective C++ (运算符)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《白鹿原》黑娃媳妇高玉凤是谁演的 最后什
- 下一篇: 利用 dbghelp.dll 生成 du