日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

EffectiveC++编程的50个建议

發(fā)布時(shí)間:2025/3/15 c/c++ 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 EffectiveC++编程的50个建议 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

        • 何時(shí)調(diào)用`copy`構(gòu)造函數(shù)
      • 視`C++`為一個(gè)語言聯(lián)邦
      • 盡量以`cosnt、enum、inline`替換`#define`
      • 盡可能使用`const`
      • 確定對(duì)象被使用之前已先被初始化
      • 了解`C++`默默編寫并調(diào)用哪些函數(shù)
      • 若不想使用編譯器自動(dòng)生成的函數(shù),就明確拒絕
      • 為多態(tài)基類聲明`virtual`析構(gòu)函數(shù)
      • 別讓異常逃離析構(gòu)函數(shù)
      • 絕對(duì)不再構(gòu)造和析構(gòu)過程中調(diào)用`virtual`函數(shù)
      • 令`operator=`返回一個(gè)`reference to *this`
      • 在`operator=`中處理`自我賦值`
      • 以對(duì)象管理資源
      • 在資源管理類中提供對(duì)原始資源的訪問
      • 成對(duì)的使用`new`和`delete`時(shí)要采取相同的形式
      • 以獨(dú)立語句將`newed`對(duì)象置入智能指針
      • 將成員變量聲明為`private`
      • 盡可能延后變量定義式的出現(xiàn)時(shí)間
      • 盡量少做轉(zhuǎn)型動(dòng)作

何時(shí)調(diào)用copy構(gòu)造函數(shù)

在構(gòu)造函數(shù)調(diào)用的時(shí)候,有的時(shí)候調(diào)用默認(rèn)構(gòu)造函數(shù),有的時(shí)候調(diào)用copy構(gòu)造函數(shù),特別是copy構(gòu)造函數(shù)的調(diào)用讓人容易和copy賦值的函數(shù)產(chǎn)生混淆。

如下對(duì)其進(jìn)行了測(cè)試:

class WidgetOperator { public:WidgetOperator() = default;;~WidgetOperator() = default;;WidgetOperator(const WidgetOperator & wo) {std::cout << "call WidgetOperator ctor" << std::endl;}WidgetOperator& operator=(const WidgetOperator& wo) {std::cout << "call WidgetOperator operator= " << std::endl;return *this;} };void WidgetOperatorTest() {std::cout << "W1" << std::endl;WidgetOperator W1; // 調(diào)用無參構(gòu)造函數(shù)std::cout << "W2(W1)" << std::endl;WidgetOperator W2(W1); // 調(diào)用copy構(gòu)造函數(shù)std::cout << "W1 = W2" << std::endl;W1 = W2; // 調(diào)用 operator=函數(shù)std::cout << "WidgetOperator W3 = W1" << std::endl;WidgetOperator W3 = W1; // 調(diào)用copy構(gòu)造函數(shù) }

執(zhí)行輸出結(jié)果:

W1 W2(W1) call WidgetOperator ctor W1 = W2 call WidgetOperator operator= W3 = W1 call WidgetOperator ctor

通過上述測(cè)試的輸出可以看出,當(dāng)調(diào)用=操作符的時(shí)候,如果一個(gè)新對(duì)象被定義。如:WidgetOperator W3 = W1;,一定會(huì)有一個(gè)構(gòu)造函數(shù)被調(diào)用,不可能調(diào)用賦值操作,反之,如果沒有一個(gè)新的對(duì)象被定義,就不會(huì)有構(gòu)造函數(shù)被調(diào)用,而只會(huì)調(diào)用賦值操作符。

視C++為一個(gè)語言聯(lián)邦

一開始C++只是C加上一些面向?qū)ο筇匦?#xff0c;但是隨著這個(gè)語言的成熟他變得更加無拘無束,接受不同于C with classes的各種觀念、特性和編程戰(zhàn)略。異常對(duì)函數(shù)的結(jié)構(gòu)化帶來了不同的做法,templates將我們帶來到新的設(shè)計(jì)思考方式,STL則定義了一個(gè)前所未見的伸展性做法。

今天C++已經(jīng)是個(gè)多重范型編程語言,一個(gè)同時(shí)支持過程形式、面向?qū)ο笮问?、函?shù)形式、泛型形式、元編程形式的語言。這些能力和彈性使C++成為一個(gè)無可匹敵的工具,因此、將C++視為一個(gè)語言聯(lián)邦。

盡量以cosnt、enum、inline替換#define

因?yàn)?、宏定義會(huì)被預(yù)處理器處理,編譯器并未看到宏定義的信息,當(dāng)出現(xiàn)一個(gè)編譯錯(cuò)誤信息的時(shí)候,可能會(huì)帶來困惑。

解決之道就是使用一個(gè)常量替換宏定義(#define)

const double AspectRatio = 1.653; // 大寫名稱通常代表宏定義,因此這里可以使用首字母大寫的方法表示const全局變量

作為一個(gè)語言常量,AspectRatio肯定會(huì)被編譯器看到,當(dāng)然就會(huì)進(jìn)入符號(hào)表內(nèi)。另外、使用常量也可以有較小的碼、因?yàn)槭褂妙A(yù)處理會(huì)導(dǎo)致預(yù)處理器盲目的將宏名稱替換為對(duì)應(yīng)的數(shù)值,可能會(huì)導(dǎo)致目標(biāo)碼出現(xiàn)多份宏定義的數(shù)值。

基于數(shù)個(gè)理由enum hack值得我們認(rèn)識(shí)。

class GamePlayer{private:enum {NumTurns = 5}; // enum hack 令NumTurns成為5的一個(gè)標(biāo)記int scores[NumTurns]; // };
  • enum hack的行為某方面來說比較像#define而不像const,有的時(shí)候這正是你想要的,例如取一個(gè)const的地址是合法的,但是取一個(gè)enum的地址就是不合法的,而取一個(gè)#define的地址通常也不合法。如果你不想讓別人獲得一個(gè)pointer或者reference指向你的某個(gè)整數(shù)常量,enum可以幫助你實(shí)現(xiàn)這個(gè)約束。
  • 雖然優(yōu)秀的編譯器不會(huì)為const對(duì)象設(shè)置存儲(chǔ)空間,但是不夠優(yōu)秀的編譯器可能會(huì)設(shè)置另外的儲(chǔ)存空間,enum和#define一樣絕對(duì)不會(huì)導(dǎo)致非必要的內(nèi)存分配。
  • 出于實(shí)用主義考慮,很多代碼特別是模板元編程中用到了它,因此、看到它你必須認(rèn)識(shí)他。

對(duì)于單純的常量,最好以const對(duì)象或者enums替換#define

對(duì)于形似函數(shù)的宏(macros),最好改用inline函數(shù)替換#define

盡可能使用const

const的一件奇妙的事情是,它允許你指定一個(gè)語義約束,而編譯器會(huì)強(qiáng)制實(shí)施這項(xiàng)約束。它允許你告訴拜你一起和其他程序員某值應(yīng)該保持不變。

char greeting[] = "Hello"; char *p = greeting; // non-const pointer, non-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語法雖然變化多端,但并不是莫測(cè)高深,如果關(guān)鍵字const出現(xiàn)在型號(hào)的左邊,表示被指物是常量,如果出現(xiàn)在星號(hào)的右邊,表示指針自身是常量,如果出現(xiàn)在星號(hào)兩邊,表示被指物和指針兩者都是常量。

如果被指物是常量,有些程序員會(huì)將關(guān)鍵字const寫在類型之前,有些人會(huì)把它寫在類型之后、星號(hào)之前,這兩種寫法的意義相同,所以下列兩個(gè)函數(shù)的參數(shù)類型是一樣的:

void f(const Widget* pw); // 一個(gè)指向常量的指針 void f2(Widget const* pw); // 一個(gè)指向常量的指針

兩種形式都有人使用,是否是指向常量的指針,要看const相對(duì)于星號(hào)的位置,星號(hào)左邊為指向常量的指針,星號(hào)右邊為常量指針。

const修飾函數(shù)返回值,可以降低編碼出現(xiàn)的低級(jí)錯(cuò)誤

class Rational {}; const Rational operator*(const Rational& lhs, const Rational& rhs); Rational a, b, c; if (a*b = c) // 其實(shí)是想做個(gè)比較,當(dāng)operator*返回值聲明為const的時(shí)候?qū)?huì)返回錯(cuò)誤,也就防止了編碼不小心帶來的異常

const修飾成員函數(shù)

  • 可以通過const得知哪些函數(shù)可以改動(dòng)對(duì)象內(nèi)容,哪些函數(shù)不可以
  • 使得操作const對(duì)象成為可能

確定對(duì)象被使用之前已先被初始化

關(guān)于將變量初始化這件事,C++似乎總是反復(fù)無常。但是有一點(diǎn)是可以確定的是,讀取沒有初始化的值會(huì)導(dǎo)致不確定行為

了解C++默默編寫并調(diào)用哪些函數(shù)

什么時(shí)候empty class不再是個(gè)空類呢?當(dāng)C++處理過之后,是的,如果你沒有自己聲明,并一起就會(huì)為它聲明(編譯器版本)一個(gè)copy構(gòu)造函數(shù)、一個(gè)copy assignment操作符和一個(gè)析構(gòu)函數(shù)。

因此、如果你聲明了一個(gè)empty class如下:

class Empty{};

編譯器處理之后就好像你寫了如下的代碼:

class Empty { public:Empty() {} // default構(gòu)造函數(shù)Empty(const Empty& rhs) {} // copy構(gòu)造函數(shù)~Empty() {} //析枸函數(shù)Empty& operator=(const Empty& rhs) {} // copy assignment 操作符 };

唯有當(dāng)這些函數(shù)被需要(被調(diào)用),它們才會(huì)被編譯器創(chuàng)建出來。

好了,我們知道編譯器會(huì)常見這些函數(shù),但這些函數(shù)做了什么?default構(gòu)造函數(shù)和析構(gòu)函數(shù),主要是給編譯器一個(gè)地方放置藏在幕后的代碼,像是調(diào)用base class和non-static成員變量的構(gòu)造函數(shù)和析構(gòu)函數(shù)。需要注意的是編譯器默認(rèn)的析構(gòu)函數(shù)是non-virtual的。

若不想使用編譯器自動(dòng)生成的函數(shù),就明確拒絕

有時(shí)你不想讓用戶使用某個(gè)函數(shù),不對(duì)函數(shù)進(jìn)行聲明就行了。但是這樣做對(duì)copy構(gòu)造函數(shù)和copy assignment操作符卻不起作用,因?yàn)椤⑷绻悴贿M(jìn)行聲明,編譯器會(huì)聲明一個(gè)默認(rèn)的出來。

這就把你逼到一個(gè)困境,如果你不想讓用戶使用copy構(gòu)造函數(shù)和copy assignment函數(shù),你既不能不聲明也不能進(jìn)行聲明。這個(gè)問題的解決方案就是,將函數(shù)聲明為私有的函數(shù),這樣你即可以阻止編譯器創(chuàng)建它們,又因?yàn)槭撬接泻瘮?shù),使得別人不能調(diào)用。

但是這樣做并不是絕對(duì)安全的,因?yàn)閙ember函數(shù)和friend函數(shù)還是可以調(diào)用private函數(shù)的。除非你足夠聰明不去定義它們,那么如果任何人不慎調(diào)用了任何一個(gè)函數(shù),將會(huì)導(dǎo)致一個(gè)鏈接錯(cuò)誤,將成員函數(shù)聲明為私有,而又故意不去實(shí)現(xiàn)它們是如此的受歡迎。、

class HomeForSale { public:... private:HomeForSale(const HomeForSale&); // 因?yàn)楦緵]有人能調(diào)用,寫參數(shù)名稱也是浪費(fèi)HomeForSale& operator=(const HomeForSale&); };

有了上述的定義之后,當(dāng)用戶企圖調(diào)用拷貝HomeForSale對(duì)象的時(shí)候,編譯器會(huì)阻止他,如果不慎在member或者friend函數(shù)中調(diào)用,連接器也會(huì)發(fā)出抱怨。

為了駁回編譯器自動(dòng)提供的功能,可將相應(yīng)的成員函數(shù)聲明為private并且不予實(shí)現(xiàn)。

為多態(tài)基類聲明virtual析構(gòu)函數(shù)

如果多條基類沒有聲明虛析構(gòu)函數(shù),那么當(dāng)通過基類指針指向一個(gè)子類對(duì)象,調(diào)用delete的時(shí)候只會(huì)調(diào)用基類的析構(gòu)函數(shù),不會(huì)調(diào)用子類的,這樣就會(huì)造成資源部分釋放的現(xiàn)象。

如果class不含有virtual函數(shù),通常表示它并不意圖被用作基類:

如一個(gè)二維空間點(diǎn)坐標(biāo)的class:

class Point { // 二維空間點(diǎn)(2D point) public:Point(int xCoord, int yCoord);~Point(); private:int x, y; };

如果int占32bits那么Point對(duì)象可以塞進(jìn)一個(gè)64-bit緩存器中。更有甚者,這個(gè)類完全可以作為一個(gè)64-bit量,傳遞給其他語言,如C,但是當(dāng)Point的析構(gòu)函數(shù)是virtual時(shí),形式就會(huì)發(fā)生變化。

欲實(shí)現(xiàn)virtual函數(shù),對(duì)象必須攜帶某些信息,主要在運(yùn)行期間決定哪個(gè)virtual函數(shù)被調(diào)用。這類信息通常由一個(gè)vptr虛函數(shù)表指針之處。vptr指向一個(gè)由函數(shù)指針構(gòu)成的數(shù)組,稱為vtbl;每一個(gè)帶有虛函數(shù)的class都有一個(gè)相應(yīng)的vtbl。

因此、無端的將所有的class的析構(gòu)函數(shù)聲明為virtual,就像從未聲明它們?yōu)関irtual一樣,都是錯(cuò)誤的。

因?yàn)闃?biāo)準(zhǔn)容器都是non-virtual的,不要試圖將其作為base-class。

別讓異常逃離析構(gòu)函數(shù)

C++并不禁止析構(gòu)函數(shù)吐出異常,但它不鼓勵(lì)你這樣做。

析枸函數(shù)絕對(duì)不要吐出任何異常,如果一個(gè)被析枸函數(shù)調(diào)用的函數(shù)可能拋出異常,析枸函數(shù)應(yīng)該捕獲任何異常,然后吞下讓夢(mèng)或結(jié)束程序

如果客戶需要對(duì)某個(gè)操作函數(shù)運(yùn)行期間拋出的異常做出反應(yīng),那么class應(yīng)該提供給一個(gè)普通函數(shù)執(zhí)行該操作

絕對(duì)不再構(gòu)造和析構(gòu)過程中調(diào)用virtual函數(shù)

你不應(yīng)該在構(gòu)造函數(shù)和析構(gòu)函數(shù)中調(diào)用virtual函數(shù),因?yàn)檫@樣的調(diào)用不會(huì)帶來你預(yù)想的結(jié)果。

構(gòu)造函數(shù)調(diào)用時(shí),因?yàn)閐erived classes沒有初始化好,會(huì)調(diào)用base class的虛函數(shù)

析構(gòu)函數(shù)調(diào)用時(shí),一旦進(jìn)入析構(gòu)函數(shù),對(duì)象中的derived classes對(duì)象便呈現(xiàn)出未定義值,所以C++視它們仿佛不再存在。

在構(gòu)造和析構(gòu)期間不要調(diào)用virtual函數(shù),因?yàn)檫@類掉用,從不降低derived class

令operator=返回一個(gè)reference to *this

關(guān)于賦值,有趣的是你可以把它們寫成連鎖的形式:

int x, y, z; x = y = z = 5;

同樣有趣的是,賦值采用右結(jié)合律,所以上述的連鎖賦值被解析為:

x = (y = (z = 15));

為了實(shí)現(xiàn)連鎖賦值,賦值操作符必須返回一個(gè)reference指向操作符的左側(cè)實(shí)參

class Widget { public:Widget& operator=(const Widget*rhs) {return *this;} };

在operator=中處理自我賦值

自我賦值發(fā)生在對(duì)象被賦值給自己時(shí):

class Widget {}; Widget w; w = w; // 賦值給自己

看起來有點(diǎn)傻,但是它是合法的,所以不要認(rèn)定客戶不會(huì)這樣做,此外賦值動(dòng)作并不總是那么可以被一眼辨認(rèn)出來:

a[i] = a[j]; // 潛在的自我賦值

一個(gè)不安全的operator=使用示例:

class BitMap {}; class Widget {private:BitMap* pb; }Widget& Widget::operator=(const Widget& rhs) {delete pb; // 停止使用當(dāng)前的bitmappb = new BitMap(*rhs.pb); // 使用rhs's bitmap的副本(復(fù)件)return *this; }

這里的問題是,當(dāng)operator=進(jìn)行自我賦值的時(shí)候,delete pb相當(dāng)于把自己的pb給刪掉了

為了防止這種錯(cuò)誤,傳統(tǒng)的做法是進(jìn)行證同測(cè)試,達(dá)到自我賦值的檢驗(yàn)的目的:

Widget& Widget::operator=(const Widget& rhs) {if (this == &rhs) return *this;delete pb; // 停止使用當(dāng)前的bitmappb = new BitMap(*rhs.pb); // 使用rhs's bitmap的副本(復(fù)件)return *this; }

swap版本的:

Widget& Widget::operator=(const Widget& rhs) {Widget temp(rhs);swap(temp);return *this; } // 或者 Widget& Widget::operator=(const Widget& rhs) {swap(rhs);return *this; }
  • 確保對(duì)象自我賦值時(shí),operator=有良好的行為,其中技術(shù)包括比較來源對(duì)象和目標(biāo)對(duì)象的地址、精心周到的語句順序、以及copy-and-swap
  • 確定任何函數(shù)如果操作一個(gè)以上的對(duì)象,其中多個(gè)對(duì)象是同一個(gè)對(duì)象時(shí),其行為仍然正確。

以對(duì)象管理資源

許多資源分配后用于單一的區(qū)域或者函數(shù)內(nèi),它們應(yīng)該在控制流離開那個(gè)區(qū)塊或函數(shù)時(shí)被釋放。標(biāo)準(zhǔn)庫auto_ptr正是對(duì)這種形勢(shì)而設(shè)計(jì)的特制產(chǎn)品。auto_ptr是個(gè)類指針對(duì)象,也就是所謂智能指針,其析枸函數(shù)自動(dòng)對(duì)其所指向?qū)ο笳{(diào)用delete

獲得資源后立即放進(jìn)管理對(duì)象內(nèi),實(shí)際上以對(duì)象管理資源的觀念被稱為資源取得時(shí)機(jī)便是初始化時(shí)機(jī)(Resource Acquisitioon Is Initialzation; RAIL)

管理對(duì)象利用析枸函數(shù)確保資源被釋放

  • 為防止資源泄露,請(qǐng)使用RAIL對(duì)象,它們?cè)跇?gòu)造函數(shù)中獲得資源并在析構(gòu)函數(shù)中釋放資源

在資源管理類中提供對(duì)原始資源的訪問

資源管理類很棒,它們是你對(duì)抗資源泄露的堡壘。但是這個(gè)世界并不是總是那么的完美,許多的APIs直接指涉資源,所以除非你發(fā)誓用不錄用這樣的APIs,否則就只能繞過資源管理對(duì)象直接訪問原始資源。

  • APIs往往要求訪問原始資源,所以每一個(gè)RAIL Class應(yīng)該提供一個(gè)取得其所管理之資源的方法
  • 對(duì)原始資源的訪問可能經(jīng)由顯示轉(zhuǎn)換或隱式轉(zhuǎn)換。一般而言顯式轉(zhuǎn)換比隱式轉(zhuǎn)換更加安全,但是隱式轉(zhuǎn)換對(duì)客戶來說比較方便

成對(duì)的使用new和delete時(shí)要采取相同的形式

一下動(dòng)作有什么錯(cuò)?

std::string* stringArray = new std::string[100];delete stringArray;

每件事情開起來都是井然有序的,使用了new也搭配了對(duì)應(yīng)的delete。但還是有樣?xùn)|西完全錯(cuò)誤,你的程序行為不明確,stringArray所包含的個(gè)string對(duì)象中的99個(gè)不太可能被適當(dāng)刪除,因?yàn)樗麄兊奈鰳?gòu)函數(shù)很可能沒有被調(diào)用。

當(dāng)你使用new有兩件事情發(fā)生,第一,內(nèi)存被分配出來;第二、針對(duì)此內(nèi)存會(huì)有一個(gè)(或更多)構(gòu)造函數(shù)被調(diào)用。當(dāng)你調(diào)用delete也有兩件事情發(fā)生,針對(duì)此內(nèi)存會(huì)有一個(gè)(或更多)析構(gòu)函數(shù)被調(diào)用,然后內(nèi)存才被釋放。delete的最大問題在于:即將刪除的內(nèi)存究竟存在多少對(duì)象,這個(gè)問題的答案決定了有多少析構(gòu)函數(shù)必須被調(diào)用起來。

因此、為了降低不必要的麻煩,不要對(duì)數(shù)組形式做typedef等操作

  • 如果你在new中使用了[],必須在相應(yīng)的delete表達(dá)式中國捏也使用[]。如果你在new表達(dá)式中沒有使用[],一定不要在相應(yīng)的delete表達(dá)式中使用[]。

以獨(dú)立語句將newed對(duì)象置入智能指針

RAIL風(fēng)格的代碼也不是什么地方都能使用,如有以下代碼:

processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority());

雖然這里借助shared_ptr實(shí)現(xiàn)了對(duì)象管理式資源,但是卻可能造成資源泄露

如果上述processWidget的調(diào)用按照如下順序進(jìn)行:

  • 調(diào)用new Widget
  • 調(diào)用tr1::shared_ptr的構(gòu)造函數(shù)
  • 調(diào)用priority函數(shù)
  • 按照上述過程調(diào)用是沒有問題的,但是C++編譯器會(huì)以什么樣的次序完成這些事情呢?答案是不一定。這正是C++區(qū)別java和C#的不同,那兩種語言總是以特定的次序完成函數(shù)參數(shù)的核算。

    如果C++編譯器按照一下的順序執(zhí)行:

  • 調(diào)用new Widget
  • 調(diào)用priority函數(shù)
  • 調(diào)用tr1::shared_ptr的構(gòu)造函數(shù)
  • 現(xiàn)在你想象下,如果priority執(zhí)行出現(xiàn)異常,會(huì)發(fā)生什么事情?在這種情況下new Widget返回的指針將會(huì)遺失,從而造成資源泄露。上述的復(fù)合語句正是造成這種資源泄露的元兇。

    如果想解決這種問題,可以通過將復(fù)合語句拆分進(jìn)行解決

    std::tr1::shared_ptr<Widget> pw(new Widget); // 在單獨(dú)語句內(nèi)以只能指針存儲(chǔ) newed出來的對(duì)象 processWidget(pw, priority()); // 這個(gè)調(diào)用即使出現(xiàn)異常也不會(huì)造成資源泄露
    • 一獨(dú)立語句將newed對(duì)象存儲(chǔ)于(置于)智能指針內(nèi)。如果不這樣做,一旦異常被拋出,有可能導(dǎo)致難以察覺的資源泄露。

    將成員變量聲明為private

    如果成員變量不是public,客戶唯一能夠訪問對(duì)象的辦法就是通過成員函數(shù)。如果public內(nèi)都是成員函數(shù),那么客戶也就不必花費(fèi)時(shí)間糾結(jié)調(diào)用成員的時(shí)候是否需要加()。

    使用函數(shù)可以讓你對(duì)成員變量實(shí)現(xiàn)更精確的控制。如果你令成員變量為public那么每個(gè)人都可以方位它,而通過函數(shù)就可以實(shí)現(xiàn)不準(zhǔn)訪問、者只讀訪問、只寫訪問和讀寫訪問。

    如果你通過函數(shù)訪問成員變量,日后可以更改某個(gè)計(jì)算替換這個(gè)成員變量,而class客戶一點(diǎn)也不會(huì)知道class的內(nèi)部實(shí)現(xiàn)已經(jīng)起了變化。

    因此、一旦你將一個(gè)成員變量聲明為一個(gè)public或者protect并且客戶開始使用,那么這個(gè)成員變量的去除將會(huì)影響所有調(diào)用它的地方,所有相關(guān)的代碼文檔測(cè)試接口都將進(jìn)行重寫。

    • 切記將成員變量聲明為private。這可賦予客戶訪問數(shù)據(jù)的一致性、可細(xì)微劃分訪問控制、允許約束條件獲得保證,并提供class作者以充分的實(shí)現(xiàn)彈性。
    • protect并不比public更具封裝性。

    盡可能延后變量定義式的出現(xiàn)時(shí)間

    只要你定義了一個(gè)變量而其類型帶有一個(gè)構(gòu)造函數(shù)或者析構(gòu)函數(shù),那么程序的控制流到達(dá)這個(gè)變量定義式時(shí),你就得承受構(gòu)造成本,當(dāng)這個(gè)變量離開其作用域時(shí),你便得承受析構(gòu)成本,即使這個(gè)變量最終并未被使用,仍需耗費(fèi)這些成本,所以你應(yīng)該盡可能避免這種情形。

    std::string encryptPassword(const std::string& password) {using namespace std;string encrypted;// 這一旦發(fā)生異常,encrypted雖然定義并被釋放,但是卻根本沒有用到if (password.length() < MinimuPasswordLength) {throw logic_error("password is too short");}...return encrypted; }
    • 盡可能延后變量定義式的出現(xiàn),這樣做可以增加程序的清晰度并改善程序的效率。

    盡量少做轉(zhuǎn)型動(dòng)作

    C++除了C語言中的強(qiáng)制類型轉(zhuǎn)換,還新增了如下新的類型轉(zhuǎn)換:

    // 將對(duì)象的常量性轉(zhuǎn)除,也就是去除const限制 const_cast<T>(expression) // 主要用于執(zhí)行安全向下轉(zhuǎn)型,也就是用來決定某個(gè)對(duì)象是否歸屬繼承體系中的某個(gè)類型 // 它是唯一無法由舊式語法執(zhí)行的動(dòng)作,也是唯一可能耗費(fèi)重大運(yùn)行成本的轉(zhuǎn)型動(dòng)作 dynamic_cast<T>(expression) // 意圖執(zhí)行低級(jí)轉(zhuǎn)型實(shí)際動(dòng)作可能取決于編譯器,這也就表示它不可移植,例如將一個(gè)pointer to int 轉(zhuǎn)型為int reinterpret_cast<T>(expression) // 用來強(qiáng)迫隱士轉(zhuǎn)換,例如將non-const對(duì)象轉(zhuǎn)換為const對(duì)象,或?qū)nt轉(zhuǎn)換為double等等,他也可以執(zhí)行上述操作的反向轉(zhuǎn)換,例如將 // void * 指針轉(zhuǎn)換為typed指針,將pointer-to-base轉(zhuǎn)為pointer-to-derived,但它無法將const轉(zhuǎn)為non-const這個(gè)只有const_cast才辦得到 static_cast<T>(expression) class Base {}; class Derived : public Base {}; Derived d; Base* pd = &d; // 隱喻地將Derived*轉(zhuǎn)換為Base* // 加入進(jìn)入一個(gè)函數(shù),你只能拿到Base* 但是你想調(diào)用Derived的函數(shù) // 你又不確認(rèn)傳進(jìn)來的是否是 Derived的對(duì)象指針,這個(gè)時(shí)候可以使用dynamic_cast // 如: if (Derived *pDerived = dynamic_cast<Derived*>pd)

    這里我們不過是建立一個(gè)base class指針指向一個(gè)derived class對(duì)象,但有時(shí)候上述兩個(gè)指針的值并不 相同。這種情況下會(huì)有一個(gè)偏移量(offset)在運(yùn)行期間被施于Derived*指針上,用意取得正確的Base*指針值。

    以上例子說明,單一對(duì)象可能擁有一個(gè)以上的地址,這種現(xiàn)象C不可能發(fā)生,java和C#也不可能發(fā)生這種事,但是C++可能!實(shí)際上一旦使用多重繼承,這種事幾乎一直發(fā)生著,即使單一繼承中也可能發(fā)生。雖然這還有其他意涵,但是至少意味著你通常應(yīng)該避免做出對(duì)象在C++中如何如何布局的假設(shè)。當(dāng)然更不應(yīng)該以此為假設(shè)的基礎(chǔ)上執(zhí)行任何轉(zhuǎn)型動(dòng)作。

    因此、依賴對(duì)象布局方式濟(jì)南西給你的地址設(shè)計(jì)方式轉(zhuǎn)型,在有的編譯器上行得通,在其他平臺(tái)可能就行不通了。

    • 如果可以,盡量避免轉(zhuǎn)型,特別是在注重效率的代碼中避免dynamic_cast,如果有個(gè)設(shè)計(jì)需要轉(zhuǎn)型操作,試著發(fā)展無需轉(zhuǎn)型的替代設(shè)計(jì)
    • 如果轉(zhuǎn)型是必須的,試著將它隱藏于某個(gè)函數(shù)背后??蛻綦S后可以調(diào)用該函數(shù),而不需將轉(zhuǎn)型放進(jìn)它們自己的代碼內(nèi)
    • 寧可使用C++新式風(fēng)格的轉(zhuǎn)型,不要使用舊式的轉(zhuǎn)型。前者容易辨認(rèn)出來。

    總結(jié)

    以上是生活随笔為你收集整理的EffectiveC++编程的50个建议的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 99视频在线看 | 久久九九视频 | 欧美日韩在线免费 | 在线免费看黄av | 深夜精品 | 日本日皮视频 | 桃花色综合影院 | 成人免费毛片视频 | 火影黄动漫免费网站 | www欧美 | 国产网站精品 | 麻豆精品在线观看 | www.欧美com | 国产精品无码中文 | 国产精品电影一区二区 | 亚洲再线 | 午夜视频在线 | 又紧又大又爽精品一区二区 | 日韩av网站在线 | 国产精品高清网站 | 日韩中文字幕免费在线观看 | 久久久精品欧美 | 国产欧美自拍 | 最近中文字幕mv | xx视频在线 | 欧美国产日韩在线 | 亚洲第九十九页 | 久久精选 | 中文字幕一区二区三区在线视频 | 中文字幕在线免费观看视频 | 日韩av电影中文字幕 | 男人和女人搞鸡 | 日本两性视频 | 99热精品在线观看 | 欧美涩涩视频 | 一本色道av | 91在线 | 99一级片 | 精品二区在线观看 | 日韩精品美女 | 超碰人人99| 中文国产字幕 | 福利视频免费观看 | 动漫美女被吸奶 | 老熟妇仑乱视频一区二区 | 成人在线视频免费观看 | 中国人妖和人妖做爰 | 天天摸天天操天天射 | 亚洲网色 | 国产av成人一区二区三区高清 | 亚洲国产精品久久久久婷婷老年 | 男生操女生动漫 | 欧美成人中文字幕 | 一区二区三区网站 | av无码久久久久久不卡网站 | 日本免费一区二区三区最新 | 国产精品天天狠天天看 | 免费一区二区三区 | 国产精品天天看 | 日韩精品一区二区三区在线 | 亚洲免费视频大全 | 98精品国产 | 日本美女黄网站 | 波多野结衣视频播放 | 中文字幕25页 | 免费观看黄色小视频 | 办公室荡乳欲伦交换bd电影 | 国产精品3区 | 久国久产久精永久网页 | 精品国产区一区二 | 国产青青操 | 男女一级片| a在线观看免费 | 精品乱码一区内射人妻无码 | 深夜福利1000 | 亚洲欧美伦理 | 久久精品国产77777蜜臀 | 在线观看黄色动漫 | 蜜臀av性久久久久蜜臀aⅴ流畅 | 日本国产精品一区 | 视频精品一区二区 | 国产亚洲欧美日韩精品一区二区三区 | 国产美女免费观看 | 99视频| 告诉我真相俄剧在线观看 | www.色网| 一区视频在线播放 | 91麻豆精品国产91久久久更新时间 | 国产福利一区在线 | 成人国产片女人爽到高潮 | 国产免费一区二区三区在线播放 | 999久久久免费精品国产 | 国产农村妇女精品久久久 | 非洲黑寡妇性猛交视频 | 国产一区二区三区电影在线观看 | 日韩精品欧美精品 | 国产美女精品一区二区三区 | 草逼网站 | 中文字幕av有码 |