a亚洲精品_精品国产91乱码一区二区三区_亚洲精品在线免费观看视频_欧美日韩亚洲国产综合_久久久久久久久久久成人_在线区

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Effective C++ - Accustoming Yourself to C++

2019-11-14 09:54:11
字體:
供稿:網(wǎng)友

Effective C++ - Accustoming Yourself to C++

前言:如何有效運(yùn)用C++,包括一般性的設(shè)計(jì)策略,以及帶有具體細(xì)節(jié)的特定語(yǔ)言特性。知道細(xì)節(jié)很重要,否則如果疏忽幾乎總是導(dǎo)致不可預(yù)期的程序行為(undefined behavior)。本文總結(jié)對(duì)于如何使用C++的一些建議,從而讓你成為一個(gè)有戰(zhàn)斗力的C++程序員。


Effective C - Accustoming Yourself to C構(gòu)造函數(shù)的explicit對(duì)象的復(fù)制命名習(xí)慣TR1和Boost視C為一個(gè)語(yǔ)言聯(lián)邦盡量以const enum inline替換define盡量使用const確定對(duì)象被使用前已先被初始化

1 構(gòu)造函數(shù)的explicit

被聲明為explicit的構(gòu)造函數(shù)通常比non-explicit更受歡迎,因?yàn)樗鼈兘咕幾g器執(zhí)行非預(yù)期的類型轉(zhuǎn)換。除非有一個(gè)好理由允許構(gòu)造函數(shù)被用于隱式類型轉(zhuǎn)換,否則把它聲明為explicit

class foo {public: explicit foo(int x);};

2 對(duì)象的復(fù)制

copy構(gòu)造函數(shù)被用來“以同型對(duì)象初始化自我對(duì)象”copy assignment操作符被用來“從另一個(gè)同型對(duì)象中拷貝其值到自我對(duì)象”。

class Widget {public: Widget(); // default構(gòu)造函數(shù) Widget(const Widget& rhs); // copy構(gòu)造函數(shù) Widget& Operator=(const Widget& rhs); // copy assignment操作符};Widget w1; // 調(diào)用default構(gòu)造函數(shù)Widget w2(w1); // 調(diào)用copy構(gòu)造函數(shù)w1 = w2; // 調(diào)用copy assignment操作符Widget w3 = w2; // 調(diào)用copy構(gòu)造函數(shù)

copy構(gòu)造和copy賦值的區(qū)別:如果一個(gè)新對(duì)象被定義,一定會(huì)有一個(gè)構(gòu)造函數(shù)被調(diào)用,不可能調(diào)用賦值操作。如果沒有新對(duì)象被定義,就不會(huì)有構(gòu)造函數(shù)被調(diào)用,那么就是賦值操作被調(diào)用。

3 命名習(xí)慣

構(gòu)造函數(shù)和析構(gòu)函數(shù)分別使用縮寫ctordtor代替。 使用lhs(left-hand side)和rhs(right-hand side)表示參數(shù)名稱。

4 TR1和Boost

TR1(Technical Report 1)是一份規(guī)范,描述加入C++標(biāo)準(zhǔn)程序庫(kù)的諸多新機(jī)能。這些機(jī)能以新的class templatesfunction templates形式體現(xiàn)。所有TR1組件都被置于命名空間tr1內(nèi)。 Boost是個(gè)組織,亦是一個(gè)網(wǎng)站,提供可移植,源代碼開放的C++程序庫(kù)。大多數(shù)TR1機(jī)能是以Boost的工作為基礎(chǔ)。

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

今天的C++已經(jīng)是個(gè)多重范型編程語(yǔ)言(multiparadigm PRogramming language),一個(gè)同時(shí)支持以下特性的語(yǔ)言: * 過程形式(procedural) * 面向?qū)ο笮问剑╫bject-oriented) * 函數(shù)形式(functional) * 泛型形式(generic) * 元編程形式(metaprogramming)

為了理解C++,你必須認(rèn)識(shí)其主要的次語(yǔ)言(sublanguage)

C 說到底C++仍是以C為基礎(chǔ)。blocks, statements, preprocessor, built-in data types, arrays, pointers等統(tǒng)統(tǒng)來自C。許多時(shí)候C++對(duì)問題的解法其實(shí)不過就是較高級(jí)的C解法,但是C++提供了C沒有的templates, exceptions, overloading(重載)等功能。

C語(yǔ)言可以重載嗎

// http://www.cplusplus.com/reference/cstdlib/qsort//* qsort example */#include <stdio.h> /* printf */#include <stdlib.h> /* qsort */int values[] = { 40, 10, 100, 90, 20, 25 };int compare (const void * a, const void * b){ return ( *(int*)a - *(int*)b );}void fun(){ printf("fun()/n");}/*$gcc -o overload_test overload_test.c overload_test.c:18:6: error: redefinition of 'fun'void fun(int a) ^overload_test.c:13:6: note: previous definition is herevoid fun() ^1 error generated. */#if 0void fun(int a){ printf("fun(int a)/n");}#endifint main (){ // 測(cè)試C語(yǔ)言是否支持overload重載 fun(); // C語(yǔ)言可以通過不同的函數(shù)指針來模擬overload重載 int n; qsort (values, 6, sizeof(int), compare); for (n=0; n<6; n++) printf ("%d ",values[n]); return 0;}

Object-Oriented C++ 這部分就是C with Classes所訴求的:

classes(包括構(gòu)造函數(shù)和析構(gòu)函數(shù))encapsulation(封裝)inheritance(繼承)polymorphism(多態(tài))virtual function(虛函數(shù)動(dòng)態(tài)綁定)etc.

Template C++ 這是C++的泛型編程(generic programming)部分,也是大多數(shù)程序員經(jīng)驗(yàn)最少的部分。

STL STL是個(gè)template程序庫(kù),它對(duì)containers, iterators, algorithms以及function objects的規(guī)約有極佳的緊密配合與協(xié)調(diào)。

6 盡量以const, enum, inline替換#define

寧可以編譯器替換預(yù)處理器。當(dāng)你做出這樣的事情:

#define aspECT_RATIO 1.653

記號(hào)名稱ASPECT_RATIO也許從未被編譯器看見,也許在編譯器開始處理源碼之前就被預(yù)處理器替換了,于是記號(hào)名稱有可能沒有進(jìn)入記號(hào)表(symbol table)內(nèi),當(dāng)你運(yùn)用此常量但獲得一個(gè)編譯錯(cuò)誤時(shí)可能會(huì)帶來困惑,因?yàn)檫@個(gè)錯(cuò)誤信息提到的是1.653而不是ASPECT_RATIO。尤其是如果ASPECT_RATIO被定義在一個(gè)非你所寫的頭文件內(nèi),你肯定對(duì)1.653來自何處毫無概念。解決的方法是:以一個(gè)常量替換上述的宏(#define)

const double AspectRatio = 1.653; // 大寫名稱通常用于宏

好處是:

作為一個(gè)語(yǔ)言常量,AspectRatio肯定會(huì)被編譯器看到,當(dāng)然就會(huì)進(jìn)入記號(hào)表內(nèi)。使用常量可能比使用#define導(dǎo)致較小量的目標(biāo)代碼,因?yàn)轭A(yù)處理器盲目地將宏名稱進(jìn)行替換會(huì)導(dǎo)致目標(biāo)代碼出現(xiàn)多份1.653,而若改用常量則不會(huì)出現(xiàn)。字符串常量,string對(duì)象通常比char*-based合適。const char* const authorName = "gerry";const std::string authorName("gerry");class專屬常量。為了將常量的作用域(scope)限制在class內(nèi),你必須讓它成為class的一個(gè)成員(member),另外為了保證此常量至多只有一份實(shí)體,必須讓它成為一個(gè)static成員。#include<stdio.h>class GamePlayer {public: void set_scores() { for (int i = 0; i != NumTurns; ++i) { scores[i] = i; } } void get_scores() { for (int i = 0; i != NumTurns; ++i) { printf("%d ", scores[i]); } printf("/n"); } static int get_numturns() { //printf("addr GamePlayer::NumTurns[%p]/n", &GamePlayer::NumTurns); return GamePlayer::NumTurns; }private: static const int NumTurns = 5; // 常量聲明 int scores[NumTurns]; // 使用該常量};int main(){ printf("GamePlayer::NumTurns[%d]/n", GamePlayer::get_numturns()); GamePlayer player; player.set_scores(); player.get_scores(); GamePlayer player2; printf("player.NumTurns[%d] player2.NumTurns[%d]/n", player.get_numturns(), player2.get_numturns()); return 0;}/*GamePlayer::NumTurns[5]0 1 2 3 4 player.NumTurns[5] player2.NumTurns[5] */

然而,上面你所看到的是NumTurns的聲明式,而非定義式。通常C++要求所使用的任何東西提供一個(gè)定義式,但如果它是class專屬常量且又是static整數(shù)類型,只要不取它們的地址,你可以聲明并使用它們而無須提供定義式

但是,如果你需要取某個(gè)class專屬常量的地址,或者編譯器要求(比如,老編譯器)需要看到一個(gè)定義式,那么需要另外提供定義式

#include<stdio.h>class GamePlayer {public: void set_scores() { for (int i = 0; i != NumTurns; ++i) { scores[i] = i; } } void get_scores() { for (int i = 0; i != NumTurns; ++i) { printf("%d ", scores[i]); } printf("/n"); } static int get_numturns() { printf("addr GamePlayer::NumTurns[%p]/n", &GamePlayer::NumTurns); return GamePlayer::NumTurns; }private: static const int NumTurns = 5; // 常量聲明 int scores[NumTurns]; // 使用該常量};const int GamePlayer::NumTurns; // NumTurns的定義int main(){ printf("GamePlayer::NumTurns[%d]/n", GamePlayer::get_numturns()); GamePlayer player; player.set_scores(); player.get_scores(); GamePlayer player2; printf("player.NumTurns[%d] player2.NumTurns[%d]/n", player.get_numturns(), player2.get_numturns()); return 0;}/*addr GamePlayer::NumTurns[0x102092f30]GamePlayer::NumTurns[5]0 1 2 3 4 addr GamePlayer::NumTurns[0x102092f30]addr GamePlayer::NumTurns[0x102092f30]player.NumTurns[5] player2.NumTurns[5]*/

通過提供定義式,我們就可以獲取class專屬常量的地址。

注意:

NumTurns的定義式中沒有賦值是因?yàn)椋琧lass常量已在聲明時(shí)獲得了初值,因此定義時(shí)不可以再設(shè)置初值。 我們無法利用#define創(chuàng)建一個(gè)class專屬常量,因?yàn)?define并不能限制作用域(scope),一旦宏被定義,它就在其后的編譯過程中有效,除非在某處被#undef。因此,#define不僅不能用來定義class專屬常量,也不能提供任何封裝性。

如果想具備作用域,但又不想取地址,可以使用enum來實(shí)現(xiàn)這個(gè)約束。

class GamePlayer {public: void set_scores() { for (int i = 0; i != NumTurns; ++i) { scores[i] = i; } } void get_scores() { for (int i = 0; i != NumTurns; ++i) { printf("%d ", scores[i]); } printf("/n"); } static int get_numturns() { //printf("addr GamePlayer::NumTurns[%p]/n", &GamePlayer::NumTurns); return GamePlayer::NumTurns; }private: //static const int NumTurns = 5; // 常量聲明 enum { NumTurns = 5, // 令NumTurns成為5的一個(gè)記號(hào)名稱 }; int scores[NumTurns]; // 使用該常量};

預(yù)處理器和宏的陷阱:

宏看起來像函數(shù),但是不會(huì)招致函數(shù)調(diào)用(function call)帶來的額外開銷。 糟糕的做法:(有效率,但不安全)

// 以a和b的較大值調(diào)用f函數(shù)#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))

好的做法:(效率和安全同時(shí)得到保證)

template<typename T>inline void callWithMax(const T& a, const T& b){ f(a > b ? a : b);}

這個(gè)template根據(jù)實(shí)例化可以產(chǎn)出一整群函數(shù),每個(gè)函數(shù)都接受兩個(gè)同類型對(duì)象,并以其中較大的調(diào)用f。這里不需要在函數(shù)本體中為參數(shù)加上括號(hào),也不需要操心參數(shù)被計(jì)算的次數(shù),同時(shí),由于callWithMax是個(gè)真正的函數(shù),它遵守作用域和訪問規(guī)則,因此可以寫出一個(gè)class內(nèi)的private inline函數(shù),而對(duì)于宏是無法完成的。

請(qǐng)記住:

對(duì)于單純常量,最好以const對(duì)象或enum替換#define 對(duì)于形似函數(shù)的宏,最好改用inline函數(shù)替換#define

7 盡量使用const

const允許你指定一個(gè)語(yǔ)義約束,也就是指定一個(gè)“不該被改動(dòng)”的對(duì)象,而編譯器會(huì)強(qiáng)制實(shí)施該項(xiàng)約束。

char greeting[] = "Hello";char* p = greeting; // non-const pointer, non-const dataconst char* p = greeting; // non-const pointer, const datachar* const p = greeting; // const pointer, non-const dataconst char* const p = greeting; // const pointer, const data

如果關(guān)鍵字const出現(xiàn)在星號(hào)左邊,表示被指物是常量;如果出現(xiàn)在星號(hào)右邊,表示指針自身是常量;如果出現(xiàn)在星號(hào)兩邊,表示被指物和指針兩者都是常量。

注意:如果被指物是常量,將關(guān)鍵字const寫在類型之前,和寫在類型之后星號(hào)之前,這兩種寫法的意義相同。

void f1(const Widget* pw);void f2(Widget const * pw);

STL迭代器系以指針為根據(jù)塑模出來,所以迭代器的作用就像個(gè)T*指針。如果你希望迭代器所指的東西不可被改變,則需要使用const_iterator

std::vector<int> vec;const std::vector<int>::iterator iter = vec.begin();*iter = 10; // ok++iter; // errorstd::vector<int>::const_iterator citer = vec.begin();*citer = 10; // error++citer; // ok

const成員函數(shù)

const實(shí)施于成員函數(shù)的目的,是為了確認(rèn)該成員函數(shù)可作用于const對(duì)象身上。這一類成員函數(shù)之所以重要,是因?yàn)椋?/p>它們使class接口比較容易被理解,可以得知哪個(gè)函數(shù)可以改動(dòng)對(duì)象內(nèi)容,而哪個(gè)函數(shù)不行。它們使“操作const對(duì)象”成為可能,這對(duì)編寫高效代碼是個(gè)關(guān)鍵,比如,改善程序效率的一個(gè)根本方法是以pass by reference-to-const方式傳遞對(duì)象,而此技術(shù)可行的前提是,我們有const成員函數(shù)可用來處理取得的const對(duì)象。

注意:兩個(gè)成員函數(shù)如果只是常量性不同,可以被重載(overload)。只有返回值類型不同的兩個(gè)函數(shù)不能重載(functions that differ only in their return type cannot be overloaded)。

#include<stdio.h>#include<iostream>#include<string>class TextBlock {public: TextBlock() { } TextBlock(const char* lhs) { text = lhs; }public: // operator[] for const object const char& operator[] (std::size_t position) const { return text[position]; } // operator[] for non-const object char& operator[] (std::size_t position) { return text[position]; }private: std::string text;};int main(){ TextBlock tb("gerry"); std::cout << tb[0] << std::endl; // 調(diào)用non-const TextBlock::operator[] const TextBlock ctb("yang"); // 調(diào)用const TextBlock::operator[] std::cout << ctb[0] << std::endl; return 0;}

成員函數(shù)如果是const意味著什么?—— bitwise constness或者physical constness VS logical constness

bitwise const指的是,成員函數(shù)只有在不更改對(duì)象之任何成員變量(static除外)時(shí)才可以說是const,即,const成員函數(shù)不可以更改對(duì)象內(nèi)任何non-static成員變量。

注意:許多成員函數(shù)雖然不完全具備const性質(zhì),卻能通過bitwise測(cè)試。比如,一個(gè)更改了”指針?biāo)肝铩钡某蓡T函數(shù),如果只有指針隸屬于對(duì)象,那么此函數(shù)為bitwise const不會(huì)引發(fā)編譯器異議,但是實(shí)際不能算是const

下面這段代碼,可以通過bitwise測(cè)試,但是實(shí)際上改變了對(duì)象的值。

#include<stdio.h>#include<iostream>#include<string>class TextBlock {public: TextBlock() { } TextBlock(char* lhs) { pText = lhs; }public: // operator[] for const object char& operator[] (std::size_t position) const { return pText[position]; }#if 0 // operator[] for non-const object char& operator[] (std::size_t position) { return pText[position]; }#endifprivate: char* pText;};int main(){ char name[] = "gerry"; const TextBlock ctb(name); std::cout << ctb[0] << std::endl; // 調(diào)用const TextBlock::operator[] char* pc = &ctb[0]; *pc = 'J'; std::cout << ctb[0] << std::endl; // 調(diào)用const TextBlock::operator[] return 0;}

logical constness主張,一個(gè)const成員函數(shù)可以修改它所處理的對(duì)象的某些bits,但只有在客戶端偵測(cè)不出的情況才可以(即,對(duì)客戶端是透明的,但是實(shí)際上對(duì)象的某些值允許改變)。正常情況下,由于bitwise const的約束,const成員函數(shù)內(nèi)是不允許修改non-static成員變量的,但是通過將一些變量聲明為mutable則可以躲過編譯器的bitwise const約束。

#include<stdio.h>#include<iostream>#include<string>#include<string.h>class TextBlock {public: TextBlock() : lengthIsValid(false) { } TextBlock(char* lhs) : lengthIsValid(false) { pText = lhs; }public: std::size_t length() const { if (!lengthIsValid) { printf("do strlen... "); textLength = std::strlen(pText); // error? 在const成員函數(shù)內(nèi)不能修改non-static成員變量 lengthIsValid = true; // 同上 } return textLength; } // operator[] for const object char& operator[] (std::size_t position) const { return pText[position]; }#if 0 // operator[] for non-const object char& operator[] (std::size_t position) { return pText[position]; }#endifprivate: char* pText; mutable std::size_t textLength; // 最近一次計(jì)算的文本區(qū)域塊長(zhǎng)度 mutable bool lengthIsValid; // 目前的長(zhǎng)度是否有效};int main(){ char name[] = "gerry"; const TextBlock ctb(name); std::cout << ctb[0] << std::endl; // 調(diào)用const TextBlock::operator[] std::cout << "length: " << ctb.length() << std::endl; char* pc = &ctb[0]; *pc = 'J'; std::cout << ctb[0] << std::endl; // 調(diào)用const TextBlock::operator[] std::cout << "length: " << ctb.length() << std::endl; return 0;}/*$./mutable glength: do strlen... 5Jlength: 5 */

constnon-const成員函數(shù)中避免重復(fù)

方法是:運(yùn)用const成員函數(shù)實(shí)現(xiàn)出其non-const孿生兄弟。

不好的做法(因?yàn)橛兄貜?fù)代碼):

// operator[] for const object const char& operator[] (std::size_t position) const { // bounds checking // log access data // verify data integrity // ... return text[position]; } // operator[] for non-const object char& operator[] (std::size_t position) { // bounds checking // log access data // verify data integrity // ... return text[position]; }

好的做法(實(shí)現(xiàn)operator[]的機(jī)能一次并使用它兩次,令其中一個(gè)調(diào)用另一個(gè)):

#include<stdio.h>#include<iostream>#include<string>class TextBlock {public: TextBlock() { } TextBlock(const char* lhs) { text = lhs; }public: // operator[] for const object const char& operator[] (std::size_t position) const { // bounds checking // log access data // verify data integrity // ... std::cout << "const char& operator[]() const/n"; return text[position]; }#if 0 // operator[] for non-const object char& operator[] (std::size_t position) { // bounds checking // log access data // verify data integrity // ... return text[position]; }#endif char& operator[] (std::size_t position) { std::cout << "char& operator[]()/n"; return const_cast<char&>(static_cast<const TextBlock&>(*this)[position]); }private: std::string text;};int main(){ TextBlock tb("gerry"); std::cout << tb[0] << std::endl; // 調(diào)用non-const TextBlock::operator[] const TextBlock ctb("yang"); // 調(diào)用const TextBlock::operator[] std::cout << ctb[0] << std::endl; return 0;}/*char& operator[]()const char& operator[]() constgconst char& operator[]() consty */

請(qǐng)記住:

將某些東西聲明為const可幫助編譯器偵測(cè)出錯(cuò)誤用法。const可被施加于任何作用域內(nèi)的對(duì)象、函數(shù)參數(shù)、函數(shù)返回類型、成員函數(shù)本體。 編譯器強(qiáng)制實(shí)施bitwise constness,但你編寫程序時(shí)應(yīng)該使用“概念上的常量性”。 當(dāng)constnon-const成員函數(shù)有著實(shí)質(zhì)等價(jià)的實(shí)現(xiàn)時(shí),令non-const版本調(diào)用const版本可避免代碼重復(fù)。

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

關(guān)于“將對(duì)象初始化”這事,C++似乎反復(fù)無常(對(duì)象的初始化動(dòng)作何時(shí)一定發(fā)生,何時(shí)不一定發(fā)生)。針對(duì)這種復(fù)雜的規(guī)則,最佳的處理方法是:永遠(yuǎn)在使用對(duì)象之前先將它初始化

對(duì)于內(nèi)置類型,必須手工完成初始化;對(duì)于內(nèi)置類型以外的其他類型,初始化責(zé)任落在構(gòu)造函數(shù)(constructors)身上,即,確保每一個(gè)構(gòu)造函數(shù)都將對(duì)象的每一個(gè)成員初始化。

構(gòu)造函數(shù)初始化的正確方法是:使用member initialization list(成員初值列),而不是在構(gòu)造函數(shù)中的賦值。因?yàn)榈谝环N方法的執(zhí)行效率通常較高(對(duì)于大多數(shù)類型而言,比起先調(diào)用default構(gòu)造函數(shù),然后再調(diào)用copy assignment操作符,單只調(diào)用一次copy構(gòu)造函數(shù)是比較高效的。對(duì)于內(nèi)置類型,其初始化和賦值的成本相同,但為了一致性最好也通過成員初值列來初始化)。

ABEntry:ABEntry(const std::string& name, const std::string& address, const std::list<PhoneNumber>& phones): theName(name), // 成員初值列表,這些都是初始化 theAddress(address), thePhones(phones), numTimesConsulted(0){ }ABEntry::ABEntry(): theName(), // 調(diào)用theName的`default`構(gòu)造函數(shù) theAddress(), // 同上 thePhones(), // 同上 numTimesConsulted(0) // 將內(nèi)置類型int顯示初始化為0{ }

C++有著十分固定的”成員初始化次序”:總是base classes更早于其derived classes被初始化。而class的成員變量總是以其聲明次序被初始化,而和它們?cè)诔蓡T初始值列中的出現(xiàn)次序無關(guān)。建議,當(dāng)你在成員初值列中初始化各個(gè)成員時(shí),最好總是和其聲明的次序一致

最后一個(gè)問題:不同編譯單元內(nèi)定義的non-local static對(duì)象的初始化順序是怎么樣的?

函數(shù)內(nèi)的static對(duì)象稱為local static對(duì)象,其他static對(duì)象稱為non-local static對(duì)象。

C++對(duì)定義于不同編譯單元內(nèi)的non-local static對(duì)象的初始化次序并無明確定義。因此,如果某編譯單元內(nèi)的某個(gè)non-local static對(duì)象的初始化動(dòng)作依賴另一編譯單元內(nèi)的某個(gè)non-local static對(duì)象,那么它所用到的這個(gè)對(duì)象可能尚未被初始化。

針對(duì)上面這個(gè)問題的解決方法是: 將每個(gè)non-local static對(duì)象搬到自己的專屬函數(shù)內(nèi),這些函數(shù)返回一個(gè)reference指向它所含的對(duì)象。即,non-local static對(duì)象被local static對(duì)象替換了。

class FileSystem { ... };FileSystem& tfs(){ static FileSystem fs; return fs;}

注意:這些函數(shù)內(nèi)含static對(duì)象的事實(shí)使它們?cè)诙嗑€程系統(tǒng)中帶有不確定性。處理這種麻煩的方法是,在程序的單線程啟動(dòng)階段,手工調(diào)用所有reference-returning函數(shù),這可消除與初始化有關(guān)的race conditions(競(jìng)速形勢(shì))

請(qǐng)記住

為內(nèi)置類型對(duì)象進(jìn)行手工初始化,因?yàn)镃++不保證初始化它們。 構(gòu)造函數(shù)最好使用成員初值列(member initialization list),而不要在構(gòu)造函數(shù)本體內(nèi)使用賦值操作(assignment)。初值列列出的成員變量,其排列次序應(yīng)該和它們?cè)赾lass中的聲明次序相同。 為免除跨編譯單元的初始化次序問題,請(qǐng)以local static對(duì)象替換non-local static對(duì)象。

下一篇: Effective C++ - Constructors, Destructors, and Assignment Operators


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 日韩免费在线观看视频 | 日韩在线观看三区 | 三区在线| 亚洲一区 | 色婷婷在线视频观看 | 久久久久中文字幕 | 日韩视频一区在线观看 | 91污片 | 日韩高清一区二区 | www.国产精品 | 久久久久国产一区 | 欧美激情一区二区三区蜜桃视频 | 太子妃好紧皇上好爽h | 国产精品久久 | 日韩大尺度电影在线观看 | 欧美成人久久 | 亚洲精品久久 | 国产精品一区二区三区视频网站 | 日韩三级精品 | 日韩欧美一区二区视频 | 在线欧美色 | 精品久久一区二区 | 国产欧美一区二区精品性色 | 呦呦av在线| 成人免费精品 | 久久精品1 | 华丽的挑战在线观看 | 伊人电院网 | 欧美精品久久久 | 日韩欧美一区二区三区久久婷婷 | av在线日韩| 精品国产一区二区三区成人影院 | 91高清视频 | 密室大逃脱第六季大神版在线观看 | 中文字幕在线免费 | 簧片免费网站 | 日韩欧美色图 | 中文字幕一区二区三区四区不卡 | 四虎新网站| 亚洲精品视频一区二区三区 | 蜜桃久久av |