1. 程式人生 > 其它 >【C++Primer筆記】第二章 變數和基本型別

【C++Primer筆記】第二章 變數和基本型別

技術標籤:C++Primer筆記c++

第二章 變數和基本型別

資料型別決定著變數所佔記憶體空間大小、該空間所能儲存的值的範圍,以及變數能參與的運算。

文章目錄

算術型別

  1. 基本內建型別使用法則

    • 數值確定不為負,用unsigned
    • 使用int進行整數運算。如果大於int(216=65536, 28=32768),使用long long型(字面值末尾加LL);
    • 在算術表示式中不要用charboolchar是否有符號視機器而定,而bool
      無論賦值為多少,轉換為整型都是0或1);
    • 執行浮點數運算用double(單精度6位,雙精度10位)。
  2. 賦給無符號型別一個超出它表示範圍的初始值時,結果是初始值模表示數值總數後的值(如unsigned char型別的-1相當於模256後的255).而賦給有符號型別一個超範圍的值時,結果是未定義的。一個算術表示式中既有無符號數又有int時,後者會自動轉換為無符號數。切勿混用帶符號型別和無符號型別!

  3. 20 //20十進位制
    024 //20八進位制
    0x14 //20十六進位制
    
  4. 轉義序列:反斜線、問號、雙引號、單引號前面都要加\。

    泛化的轉義序列:\x後面跟一個十六進位制數字,或者\後面跟一個不超過三位的八進位制數字。

定義和宣告

  1. 使用列表初始化時,如果初始值存在丟失資訊的風險,編譯器會報錯。

    double val = 3.141592653;
    int a = {val}; //報錯
    int b = val; //不報錯
    
  2. **定義於任何函式體之外的變數被初始化為0(包括main函式),而定義在函式體內部的內建型別變數不被初始化。**不被初始化的變數,值是未定義的(Codeblocks裡是隨機數)。建議初始化每一個內建型別變數。

  3. 如果要在多個檔案中使用同一個變數,就必須把宣告和定義分離:在一個檔案中定義變數(不一定要加extern),而在其他檔案中對其進行宣告。

    extern int i; //不能初始化,否則則為定義
    
  4. **當你第一次使用變數時,再去定義它!**在內層作用域中,可以重新定義外層作用域已有的名字。這樣,前者會覆蓋後者。再次訪問後者需要使用::操作符。如果函式可能用到一個全域性變數,則不應再定義一個同名的區域性變數。

引用和指標

  1. 複合型別:引用和指標。**引用只是為一個已有物件起的別名,本身並不是物件(而指標本身是一個物件)。引用無法解綁,必須初始化(和指標不同)。引用、指標型別必須和物件型別嚴格匹配。**定義方式如下:

    int *p1, p2, &r3;
    //p1是指標,p2是int型物件,p3是引用
    
  2. 只有有效指標才能解引用。void*型指標可以存放任意型別物件的地址,但不能解引用,只能用作函式輸入輸出、和其他指標比較,或者賦值給另一個void*指標。

  3. 空指標:

    int *p1 = nullptr; 
    int *p2 = 0;
    
  4. 等定義物件後再定義指向它的指標。若實在不知道指標指向何處,就初始化為nullptr

  5. 賦值改變的是永遠是等號左側的物件!

  6. 不存在指向引用的指標(因為引用不是物件),但是存在對指標的引用:

    int val = 32;
    int *p = &val;
    int *&r = p; //r是一個對指標p的引用
    

Const

  1. 凡是定義後不能更改的變數必須初始化。如const型變數、引用變數。

  2. const物件預設情況下只在檔案內有效。如果要多個檔案共用,定義和宣告時都要加extern

  3. 允許一個對const的引用(常量引用)繫結非常量物件、字面值、表示式。而普通引用無法繫結到常量物件或常量引用身上。雖然不能修改常量引用的值,但仍能通過其他途徑修改被引用的物件。

    int i = 42;
    const int &r = i;
    i = 0;
    r = 1; //錯誤!
    
  4. 指向常量的指標與常量引用類似(底層const):只是不能通過解引用修改指向的物件而已,通過其他途徑修改還是可以的。但是這種指標可以不用初始化,也可以改變它的指向。

  5. 常量指標本身是一個常量,所以必須初始化,且不能修改其值(地址)。還是可以通過從右往左原則記憶(最右邊的代表其屬性)。

    int i;
    const int *i1; //指向常量的指標
    int *const i2 = &i; //常量指標
    
  6. 對頂層const(普通、常量指標)的拷貝沒有限制。而對於底層const(常量引用和指向常量的指標),只能常量之間拷貝,或者非常量轉換為常量。

Constexpr

  1. 只有包含const修飾符、初始值為字面值型別(或為用常量表達式初始化的const物件)的表示式才是常量表達式(注:字面值型別包括整型(包括布林型和字元型)、浮點型、引用和指標)。

    const int max = 100; //max是常量表達式
    const int limit = max + 1; //limit是常量表達式
    int is = 27; //is不是常量表達式
    const int s = getSize(); //s不是常量表達式
    
  2. 宣告為constexpr的變數(頂層const)一定是一個常量。如果認定一個變數是常量表達式,就把它宣告為constexpr

  3. constexpr指標只能初始化為nullptr或常量的地址。不過,由於定義於所有函式之外的變數的地址固定不變,它們是可以用來初始化constexpr指標的。注意寫法:

    constexpr int *p = 0; //和指向常量的指標是完全不同的!
    

處理型別

typedef

  1. 類型別名的宣告方法:

    typedef double wages; //傳統方法
    typedef wages base, *p; //p是double*型別
    // using wages = double; //C++11的新方法
    

    注意:

    typedef char *p;
    const p cspr = 0; //cspr是一個常量指標,而不是指向常量的指標
    

auto

  1. auto型別說明符能讓編譯器自主判斷型別。顯然,auto定義的變數必須初始化。一條宣告語句中所有變數的初始基本資料型別必須相同。

    double val1, val2;
    auto val = val1 +val2; //由右側的表示式推出val是double型
    auto sz = 0, pi = 3.14; //錯誤!
    
  2. auto預設會忽略掉引用和頂層const特性:

    int i = 0, &r = i;
    auto a = r; //a是整型變數,而非對整型的引用
    const int ci = i, &cr = ci;
    auto b = ci; //b是整型變數(頂層const)
    auto c = &cr; //c是指向整型常量的指標(底層const)
    
  3. 如果想要推出頂層const型,要在auto前面加上const

  4. 設定一個型別為auto的引用時,初始值中的頂層屬性仍然保留,且原來的初始化規則仍然適用。

    auto &g = ci; //g是一個整型常量引用
    auto &h = 42; //錯誤!不能為非常量引用繫結字面值
    const auto &j = 42; //正確!
    

decltype

  1. decltype()返回運算元的資料型別(當你想知道這個表示式的資料型別,而又不想用這個表示式的值作為初始值的時候,用decltype而不用auto)。

  2. decltype返回的型別包括引用和頂層const在內(引用從來都只作為其引用物件的同義詞(代名詞)出現,只有在decltype是個例外)。

  3. 一些使用法則:

    int i = 32, *p = &i, &r = i;
    decltype(r+0) b; //正確!使用加法後變為整型,而非整型引用
    decltype(*p) c; //錯誤!指標解引用後返回引用型別,要初始化
    decltype((i)) d; //錯誤!兩個括號得到引用型別
    

自定義資料結構

  1. 建議定義分開寫,不要合在一起:

    struct Data{...};
    Data d1, d2;
    
  2. 標頭檔案通常包含類、const變數、constexpr變數等。

  3. 標頭檔案保護符:為了防止重複定義某一標頭檔案。

    #ifndef SALES_DATA_H //如果還沒被定義過
    #define SALES_DATA_H //定義
    #include <string> 
    //string標頭檔案裡也寫了標頭檔案保護符,就不會被重複定義
    struct SalesData {
    	std::string bookName;
    	double revenue = 0.0;
    };
    #endif