2018-09-16

Effective c++第三版

讓自己習(xí)慣C++

條款01:視C++為一個語言聯(lián)邦

  • C++是一個同時支持過程形式拇惋、面向?qū)ο笮问健⒑瘮?shù)形式眷柔、泛型形式、元編程形式的語言
  • 了解四個次語言

C
Object-Oriented C++
Template C++
STL

C++高效編程守則視情況而變化驴一,取決于你使用C++的哪一個部分

條款02:盡量以const、enum灶壶、inline替換#define

  • 盡量不使用#define
#define ASPECT_RATIO 1.653

ASPECT_RATIO可能沒有進(jìn)入記號表內(nèi)肝断,當(dāng)運用這個常量時獲得一個編譯錯誤的信息時,可能會出現(xiàn)問題,因為錯誤信息可能會只提到1.653這個數(shù)值而不是ASPECT_RATIO胸懈。如果ASPECT_RATIO被定義在非自己所寫的文件里担扑,排查錯誤將非常麻煩。

  • 解決方法
    用一個常量替換上述的宏:
const double AspectRatio = 1.653;    

AspectRatio是一個語言常量趣钱,肯定能夠被編譯器所看見涌献,即會進(jìn)入記號表中。且使用常量可能比使用#define導(dǎo)致較小量的碼首有。

  • 兩種特殊情況
    1.定義常量指針燕垃。常量指針通常放在頭文件中,因此有必要將指針?biāo)傅牡刂仿暶鳛閏onst井联。則就要用指向常量的常指針卜壕。如:
const char* const authorName = "S

2.class專屬常量。為了將常量的作用域限制于class內(nèi)低矮,你必須讓他成為class的一個成員。而為了確保常量只有一個實體被冒,你必須使他成為一個static成員:

class GamePlayer
{
private:
    static const int NumTurns = 5;    //常量聲明式
    int scores[NumTurns];
    ...
};

其中NumTurns是一個聲明式军掂,而不是一個定義式。如果要取某個class專屬常量的地址昨悼,必須提供定義式如下:

const int GamePlayer::NumTurns;    //NumTurns的定義蝗锥;
                                                          //下面說明為什么沒有給予數(shù)值

這個式子放入實現(xiàn)文件(cpp文件)而非頭文件。由于class常量在聲明時獲得初值率触,因此不可以再設(shè)初值终议。
注意,我們無法利用#define創(chuàng)建一個class專屬常量葱蝗,因為#define不重視作用域穴张。一旦宏被定義,它就在其后的編譯過程中有效两曼。#define不能夠用來定義class專屬常量皂甘,也不能夠提供任何封裝性。
如果編譯器不支持上述語言悼凑,可作如下改變:

class CostEstimate
{
private:
    static const double FudegeFactor;    //static class常量聲明
    ...                                                       //位于頭文件內(nèi)
};
const double CostEstimate::FudegeFactor = 1.35;    //位于實現(xiàn)文件內(nèi)

但是上述中的GamePlayer::scores的數(shù)組必須要知道常量值偿枕。可以改用所謂的the enum hack補償做法户辫。
其理論依據(jù)是:“一個屬于枚舉類型的數(shù)值可權(quán)充ints被使用”渐夸,于是GamerPlayer可定義如下:

class GamePlayer
{
private:
    enum { Numturns = 5};    //"the enum hack"  令NumTurns成為5的一個記號名稱就沒問題了

    int scores[NumTurns]
    ...
};

enum hack的行為比較像#define而不像const,有時候這正是你想要的渔欢。例如取一個const的地址是合法的墓塌,但取一個enum的地址就不合法,取#define的地址通常也不合法。
如果你不像讓別人活得一個指針或者引用指向你的某個整數(shù)常量桃纯,enum可以幫助你實現(xiàn)這個目標(biāo)酷誓。
enum hac—>實用主義,是模板元編程的基礎(chǔ)技術(shù)态坦。
當(dāng)宏帶著宏實參時可以用模板內(nèi)聯(lián)函數(shù)取代:

#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b)) 
//可被取代為:

template<typename T>
inline void callWithMax(const T& a,const T& b)    //不知道T是什么盐数,因此采用常引用采值的方式
{
    f(a > b ? a : b);
}

callWithMax是個真正的函數(shù),它遵守作用域和訪問規(guī)則伞梯。即可以用于class中玫氢,作為一個private inline 函數(shù)。
有了const谜诫、enum漾峡、inline,我們隊預(yù)處理器的需求降低了喻旷。

  • 對于單純常量生逸,最好以constexpr、const對象或者enum替換#define且预。
  • 對于形似函數(shù)的宏槽袄,最好改用inline函數(shù)替換#define。

條款03: 盡可能使用const

const可修飾它在class外部global或namespace作用域的常量锋谐,或修飾文件遍尺、函數(shù)、區(qū)塊作用域中被聲明為static的對象涮拗。也可修飾class內(nèi)部中static和non-static成員變量乾戏。對于指針,可修飾指針本身不可變三热,指針?biāo)肝锊豢勺児脑瘢蛘邇烧叨疾皇腔蚨际莄onst:

char greeting[ ] = "hello";
char* p = greeting;    //非常量指針
const char* p = greeting;    //指向常量的指針
const char* const p = greeting;    //指向常量的常指針

const出現(xiàn)在星號左邊,表示被指物是常量就漾。如果出現(xiàn)在星號右邊惯退,則表示指針是常量,如果出現(xiàn)在星號兩邊从藤,表示被指物和指針都是常量催跪。

const int * = int const *;

STL迭代器以指針為根據(jù)塑模出來,迭代器的作用就像個T指針夷野。聲明迭代器為const就相當(dāng)于聲明指針為const一樣(T const指針)懊蒸,表示一個常指針,如果你希望STL模擬一個const T*指針悯搔,你需要的是const_iterator:

std::vector<int> vec;
...
const std::vector<int>::iterator iter = vec.begin();    //iter的作用像個T* const
*iter = 10骑丸;    //沒問題,改變iter所指物
++iter;    //錯誤! iter是const
std::vector<int>::cosnt_iterator cIter = vec.begin(); 
*cIter = 10;    //錯誤通危!cIter是const
++cIter;    //正確铸豁,改變cIter 

面對函數(shù)聲明時,const可以和函數(shù)返回值菊碟、各參數(shù)节芥、函數(shù)自身產(chǎn)生關(guān)聯(lián)。
令函數(shù)返回一個常量值逆害,往往可以降低因客戶錯誤而造成的意外头镊,且保證了安全性和高效性。例如:
有理數(shù)的operator*聲明式魄幕。

class Rational {...};
const Rational operator* (const Rational& lhs, const Rational &rhs);

為什么要返回一個const對象相艇?因為用戶可能會產(chǎn)生這樣的行為:

Rational a, b, c;
...
(a * b) = c;    //在a*b的成果上調(diào)用operator=

程序員可能在做bool運算時,不經(jīng)意間這么做:

if( a*b = c)...    //其實只是想做一個比較的操作

如果a纯陨,b是內(nèi)置類型坛芽,顯然不合法,而一個“良好的用戶自定義類型”的特征是它們避免無端地與內(nèi)置類型不兼容(見條款18)翼抠,因此才將operator*的回傳值聲明為const咙轩,預(yù)防上面的操作。
我們應(yīng)該在必要的時候使用const机久,避免出現(xiàn)鍵入“==”卻意外鍵成“=”的錯誤臭墨。

const成員函數(shù)

const實施于成員函數(shù)的目的是為了確認(rèn)該成員函數(shù)可作用于const對象赔嚎。這一類成員函數(shù)之所以重要膘盖,原因如下:
1.它們使class接口比較容易被理解。這是因為尤误,得知哪個函數(shù)可以改動對象內(nèi)容而哪個函數(shù)不行侠畔。
2.它們使“操作const對象”成為可能。因為如條款20所言损晤,改善c++程序效率的根本方法是以pass by reference-to-const方式傳遞對象软棺,而此技術(shù)可行的前提條件是,我們有const成員函數(shù)可以用來處理取得的const對象尤勋。
兩個成員函數(shù)如果只是常量性不同喘落,可以被重載。

class TextBlock
{
public:
  ...
  const char& operator[ ] (std::size_t position) const
  {return text[position];}    //const對象
  char& operator[ ] (std::size_t position)
  {return text[position];}    //non-const對象
  private:
   std::string text;
};    

void print(const TextBlock& ctb)
{
    std::cout<<ctb[0];    //調(diào)用const TextBlock::operator[]
     ...

只要重載operator[ ]并對不同的版本給予不同的返回類型最冰,就可以令const和non-const TextBlocks獲得不同的處理:

std::cout << tb[0];    //沒問題
tb[0]= 'x';    //沒問題
std::cout<< ctb[0];    //沒問題
ctb[0] = 'x'    //錯誤

上述錯誤只因operator[ ]的返回類型導(dǎo)致的瘦棋,錯在對于一個返回值為const char&實施賦值。
對于想要在const成員函數(shù)中改變類中成員變量的值暖哨,此時應(yīng)該將該成員變量聲明為mutable赌朋。

class CTextBlock
{
public:
    ...
    std::size_t length() const;
private:
    char* pText;
    std::size_t textLength;    
    bool lengthIsValid;
};
std::size_t CTextBlock::length() const
{
    if(!lengthIsValid)
    {
        textLength = std::strlen(pText);    //錯誤!在const成員函數(shù)內(nèi)
        lengthIsValid = true;    //不能賦值給lengthIsValid和textLength
      }
      return textLength;
}
//改
class CTextBlock
{
public:
      ...
      std::size_t length() const;
private:
      char* pText;
      mutable std::size_t textLength;    //此成員變量可以在const成員函數(shù)里更改
      mutable bool lengthIsValid    //此成員函數(shù)也可以在const成員函數(shù)中更改
};
std:: size_t CTextBlock::length() const
{
      if(!lengthIsValid){
        textLength = std::strlen(pText);
        lengthIsValid = true;
      return textLength;
}
在const和non-const成員函數(shù)中避免重復(fù)
class TextBlock
{
public:
    ...
    const char& operator[](std::size_t position) const
{
    ...
    ...
    ...
    return text[positon];
}
char& ooperator[ ] (std::size_t position)
{
    ...
    ...  
    ...
    return text[position];
}
private:
      std::string text;
};

兩個版本的operator[]函數(shù)重復(fù)了一些代碼,應(yīng)該做的是實現(xiàn)operator[ ]的技能一次并使用它兩次沛慢。令另一個調(diào)用另一個赡若。即:

class TextBlock
{
public:
      ...
      const char& operator[ ] (std::size_t position) const
{
      ...
      ...
      ...
      return text[position];
}
    char& operator[ ](std::size_t position)
{
    return const_cast<char&>(static_cast<const TextBlock&>(*this)[positon]);
}
      ...
};

第一次將TextBlock& 轉(zhuǎn)型為const TextBlock&。第二次則是從const operator[ ]的返回值中移除const

請記住
  1. 將某些東西聲明為const可幫助編譯器偵測出錯誤用法团甲。const可被施加于任何作用域內(nèi)的對象逾冬、函數(shù)參數(shù)、函數(shù)返回類型伐庭、成員函數(shù)本體粉渠。
  2. 編譯器強(qiáng)制實施bitwise constness
  3. 當(dāng)const和non-const成員函數(shù)有著實質(zhì)等價的實現(xiàn)時,令non-const版本調(diào)用const版本可避免代碼重復(fù)圾另。

條款04:確定對象被使用前已被初始化

C++中的對象初始化反復(fù)無常霸株。如果這樣寫:

int x;

在某些語境下x保證被初始化(為0),但在其他語境中卻不能保證集乔。

class Point
{
    int x, y;
};
...
Point p;

p的成員變量由時候被初始化(為0)去件,有時候不會。
讀取為初始化的值會導(dǎo)致不明確行為扰路。有可能導(dǎo)致程序終止運行尤溜。導(dǎo)致一些不可測的行為。
好的處理方式是:永遠(yuǎn)在使用對象之前先將它初始化汗唱。對于無任何成員的內(nèi)置類型宫莱,你必須手工完成此事。例如:

int x = 0;    //對int進(jìn)行手工初始化
const char* text = "A C-style string";    //對指針進(jìn)行手工初始化
double d;
std::cin>>d;    //以讀取input stream的方式完成初始化

至于內(nèi)置類型之外的任何其他東西哩罪,初始化責(zé)任落在構(gòu)造函數(shù)身上授霸。即:確保每一個構(gòu)造函數(shù)都將對象的每一個成員初始化。
注意:不能混淆賦值和初始化际插。

class PhoneNumber {...};
class ABEntry
{
public:
    ABEntry(const std::string&  name, const std::string& address,
                  const std::list<PhoneNumber>& phones;
private:
    std::string theName;
    std::string theAddress;
    std::list<PhoneNumber> thePhones;
    int numTimesConsulted;
};
ABEntry::ABEntry(const std::string& name, const std::string& address,
                              const std::list<PhoneNumber>& phones)
{
      theName = name;
      theAddress = address;    //這些都是賦值而非初始化
      thePhones = phones;
      numTimesConsulted = 0;
}

這會導(dǎo)致ABEntry對象帶有你期望的值碘耳,但不是最佳做法。C++規(guī)定框弛,對象的成員變量的初始化動作發(fā)生在進(jìn)入構(gòu)造函數(shù)本體之前辛辨。在ABEntry構(gòu)造函數(shù)內(nèi),theName瑟枫、theAddress和thePhones都不是被初始化斗搞,而是被賦值。初始化的發(fā)生時間更早慷妙,發(fā)生于這些成員的default構(gòu)造函數(shù)被自動調(diào)用之時僻焚。
ABEntry構(gòu)造函數(shù)的一個較好的寫法是,使用所謂的成員初始值列表化替換賦值操作:

ABEntry::ABEntry(const std::string& name, const std::string& address,     //現(xiàn)在這些都是初始化
                                const std::list<PhoneNumber>& phones)   
                                :theName(name),theAddress(address),thePhones(phones),numTimesConsulted(0)
{  }

這個構(gòu)造函數(shù)和上一個的最終結(jié)果相同景殷,但通常效率較高溅呢≡杪牛基于賦值的那個版本首先調(diào)用默認(rèn)構(gòu)造函數(shù)為theName、theAddress和thePhones設(shè)初值咐旧,然后立刻對他們賦予新值驶鹉。default構(gòu)造函數(shù)的一切作為因此浪費了。成員初始化列表的做法避免了這個問題铣墨,因為初始列中針對各個成員變量而設(shè)的實參室埋,被拿去作為各成員變量之構(gòu)造函數(shù)的實參。
對于內(nèi)置對象如numTimesConsulted伊约,其初始化和賦值的成本相同姚淆,但為了一致性最好也通過成員初始化。

ABEntry::ABEntry( )
    :theName(), theAddress(), thePhones(),    //調(diào)用theNmae屡律、theAddress腌逢、thePhones的默認(rèn)構(gòu)造函數(shù)
     numTimesConsulted(0)    //記得將numTimesConsulted顯示初始化為0
{...}
  • 我們立下一個規(guī)則:總是在初始列中列出所有成員變量。

有些情況下即使面對的成員變量屬于內(nèi)置類型超埋,也一定要使用初值列(int x(5))搏讶。如果成員變量是const或引用,它們就一定需要初值霍殴,不能被賦值(見條款5)媒惕。

為避免需要記住成員變量何時必須在成員初始化列表,何時不需要来庭。一個簡單的做法是:

  • 總是使用成員初始化列表妒蔚。

當(dāng)許多class擁有多個構(gòu)造函數(shù),存在許多成員變量和或者base class月弛,可以合理地在成員初始化列表中遺漏哪些“賦值表現(xiàn)和初始化一樣好”得成員變量肴盏,改用它們的賦值操作,并將那些賦值操作移往某個函數(shù)(通常是private)尊搬,供所有構(gòu)造函數(shù)調(diào)用叁鉴。當(dāng)成員變量的初值是由文件或數(shù)據(jù)庫讀入時特別有用土涝。

比起由賦值操作完成的“偽初始化”佛寿,通過成員初始化列表完成的“真正初始化”通常更加可取。

C++有著固定的“成員初始化次序”但壮〖叫海基類應(yīng)該比其子類更先被初始化(見條款12),而class的成員變量總是以其聲明次序依次被初始化蜡饵。如上述中的ABEntry類弹渔,其中theName、theAddress溯祸、thePhones依次被初始化肢专。

注意:兩個成員變量的初始化或許必須帶有次序性舞肆。例如初始化數(shù)組時要指定大小,即代表大小的成員要先被初始化博杖。

當(dāng)內(nèi)置型成員變量明確地加以初始化椿胯,而且也確保你的構(gòu)造函數(shù)運用“成員初始化列表”初始化基類和成員變量,剩下的就是不同編譯單元內(nèi)定義的非局部靜態(tài)對象的初始化次序剃根。

static對象:存在時間是從被構(gòu)造出來知道程序結(jié)束為止哩盲,因此stack和hea-based對象都被排除。static對象包括全局對象狈醉、定義域namespace作用域內(nèi)的對象廉油、在class內(nèi)、函數(shù)內(nèi)苗傅、以及在file作用域內(nèi)被聲明為static的對象抒线。函數(shù)內(nèi)的static對象稱為local static對象,其他static對象稱為non-local static對象渣慕。程序結(jié)束時static對象會自動銷毀十兢,即在main()結(jié)束時自動調(diào)用其的析構(gòu)函數(shù)。

編譯單元:單一目標(biāo)文件的源代碼摇庙。即:單一源碼文件加上其所含的頭文件旱物。

  • non-local static對象在main()開始之前就已經(jīng)被構(gòu)造出來了

現(xiàn)在,我們關(guān)心的問題設(shè)計兩個源碼文件卫袒,每一個至少有一個non-local static對象宵呛。
問題:如果某編譯單元內(nèi)的某個non-loacl static 對象的初始化動作使用了另一個編譯單元內(nèi)的某個non-local static對象,它所用到的這個對象可能尚未初始化夕凝,因為C++對“定義于不同編譯單元內(nèi)的non-local static對象”的初始化次序并無明確定義宝穗。

實例如下:

class FileSystem
{
public:
    ...
    std::size_t numDisks()  const;    //眾多成員函數(shù)之一
    ...
};
extern FileSystem tfs;    //預(yù)備給客戶使用的對象;
//另一個class
class Directory
{
public:
    Directory( params );
    ...
};
Directory::Directory( params)
{
    ...
    std::size_t disks = tfs.numDisks( );    //使用tfs對象
    ...
}
//進(jìn)一步假設(shè)码秉,這些客戶決定創(chuàng)建一個Directory對象逮矛,用來放置臨時文件:
Directory tempDir( params );    //為臨時文件而做出的目錄

現(xiàn)在,初始化次序的重要性就體現(xiàn)出來了:除非tfs在tempDir之前先被初始化转砖,否則tempDir的構(gòu)造函數(shù)會用到未初始化的tfs须鼎。由于tfs和tempDir是不同的人在不同的時間于不同的源代碼建立恰里的,他們是定義于不同編譯單元內(nèi)的non-local static對象府蔗。如何確定tfs在tempDir之前被初始化呢晋控?

答案是無法確定。
此問題的解決辦法:即將每個non-local static對象搬到自己的專屬函數(shù)內(nèi)(該對象在此函數(shù)內(nèi)被聲明為static)姓赤,這些函數(shù)返回一個引用指向它所含的對象赡译。然后用戶調(diào)用這些函數(shù),而不直接指涉這些對象不铆。換句話說蝌焚,non-local static對象被local static對象替換了裹唆。這是單例模式的一個常見實現(xiàn)手法。
此技術(shù)在tfs和temp身上只洒,結(jié)果如下:

class FileSystem {...};
FileSystem& tfs()    //使用函數(shù)來代替tfs對象品腹。
{
static FileSystem fs;    //定義并初始化一個local static對象,返回一個引用指向上述對象红碑。
return fs;
}
class Directory {...};    //同上
Directory::Dorectory(params)
{
    ...
    std::size_t disks = tfs().numDisks();
    ...
}
Directory& tempDir()
{
    static Directory td;    //同上
    return td;
}

這樣修改之后舞吭,系統(tǒng)程序的客戶完全可以像以前一樣地使用它。不同之處是tfs析珊、tempDir變成了tfs()\tempDir()羡鸥。這種做法可能在多線程的情況下有問題。

運用引用-返回函數(shù)防止“初始化次序問題”忠寻,前提是其中有著一個對對象而言合理的初始化次序惧浴。即:如果對象A的初始化必須在B之前初始化,但是A能否初始化成功卻又受制于B是否已初始化奕剃。這樣就存在問題衷旅。

為了避免在對象初始化之前過早地使用它們,你需要做三件事纵朋。
1.手工初始化內(nèi)置型的非成員對象柿顶。
2.使用成員初始化列表

請記住

  • 為內(nèi)置型對象進(jìn)行手工初始化。
  • 構(gòu)造函數(shù)最好使用成員初始化列表操软,不要在構(gòu)造函數(shù)本體內(nèi)使用賦值操作嘁锯。初始化列表中的成員變量的次序應(yīng)該和它們在class
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市聂薪,隨后出現(xiàn)的幾起案子家乘,更是在濱河造成了極大的恐慌,老刑警劉巖藏澳,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仁锯,死亡現(xiàn)場離奇詭異,居然都是意外死亡翔悠,警方通過查閱死者的電腦和手機(jī)业崖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凉驻,“玉大人腻要,你說我怎么就攤上這事复罐。” “怎么了?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵昭伸,是天一觀的道長。 經(jīng)常有香客問我趟济,道長,這世上最難降的妖魔是什么咽笼? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任顷编,我火速辦了婚禮,結(jié)果婚禮上剑刑,老公的妹妹穿的比我還像新娘媳纬。我一直安慰自己,他們只是感情好施掏,可當(dāng)我...
    茶點故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布钮惠。 她就那樣靜靜地躺著,像睡著了一般七芭。 火紅的嫁衣襯著肌膚如雪素挽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天狸驳,我揣著相機(jī)與錄音预明,去河邊找鬼。 笑死耙箍,一個胖子當(dāng)著我的面吹牛撰糠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播辩昆,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼窗慎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了卤材?” 一聲冷哼從身側(cè)響起遮斥,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎扇丛,沒想到半個月后术吗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡帆精,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年较屿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卓练。...
    茶點故事閱讀 40,742評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡隘蝎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出襟企,到底是詐尸還是另有隱情嘱么,我是刑警寧澤,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布顽悼,位于F島的核電站曼振,受9級特大地震影響几迄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜冰评,卻給世界環(huán)境...
    茶點故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一映胁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧甲雅,春花似錦解孙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至函匕,卻和暖如春娱据,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背盅惜。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工中剩, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人抒寂。 一個月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓结啼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親屈芜。 傳聞我的和親對象是個殘疾皇子郊愧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,747評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,523評論 1 51
  • 1.C和C++的區(qū)別?C++的特性井佑?面向?qū)ο缶幊痰暮锰帲?答:c++在c的基礎(chǔ)上增添類属铁,C是一個結(jié)構(gòu)化語言,它的重...
    杰倫哎呦哎呦閱讀 9,536評論 0 45
  • C++文件 例:從文件income. in中讀入收入直到文件結(jié)束躬翁,并將收入和稅金輸出到文件tax. out焦蘑。 檢查...
    SeanC52111閱讀 2,799評論 0 3
  • 基本情況# 姓名:雷智超 年齡:11歲 小組:第1組 #90天目標(biāo)及完成情況# 1、家長目標(biāo): 第一個30天 早睡...
    郭娟666閱讀 193評論 0 0