c++學習

名字好难想zzz發表於2024-07-12

20240712

最近開始看候捷的c++影片,影片是從類開始講的,過程中發現很多c的知識有點忘了,而且c++也有很多新的語法特性。因此看完前幾個影片後花點時間過一下c++ primer前六章,記錄一下需要學習的c++新特性和程式碼規範。

  • 學引用時有點亂,抽時間搞一下值型別的總結

#第二章

基本型別

long long型別:64位

  1. 數值不為負時使用unsinged,這裡尤其要注意迴圈的使用

錯誤例子:

//死迴圈程式碼
for(unsigned a =10; a>=0; a--)
  1. 最優先使用的型別:整數int,浮點數double,超越int範圍long long

  2. char在一些機器上是有符號的而一些上是無符號的,因此使用時要明確指定signed char或者unsigned char

變數

  1. 字面值常量,其形式和型別決定它的資料型別,可以使用字首或者字尾進行指定

  2. c++11新特性,列表初始化

  • 統一語法:使用花括號{}進行初始化。

  • 自動避免窄化轉換:在列表初始化中,如果初始化過程會導致資料丟失(如,從 double 到 int 的轉換),編譯器會報錯。

    int a{1.1};
    
  • 適用於所有型別:包括 POD(Plain Old Data)型別、聚合型別、類型別等。

  1. 變數的宣告與定義:用於分離式編譯
  • 變數宣告規定變數的型別與名字,使用關鍵字 extern

  • 定義則在宣告的基礎上為之申請儲存空間

extern int a;/宣告
int a;//宣告並定義
extern int a = 1;//定義

變數只能被定義一次,但能夠進行多次宣告。在多個檔案中使用同一個變數時,其定義只能出現在一個檔案中,其他使用時需進行宣告。

  • 型別檢查:c++作為靜態型別語言,編譯器在編譯階段對變數進行型別檢查,因此在使用變數時必須進行宣告,也就是說賦予其型別。
  1. 注意作用域與作用域運算子

複合型別

這裡由於&,*這兩個符號的多重意義,在作為宣告的一部分出現時最好和資料型別寫在一起

引用

c++11中分為左值引用、常量左值引用、右值引用。這裡先只學習左值引用

  1. 左值引用(即通常意義下的引用)

語法:

int a=1;
int& refa1=a;//refa是對a的引用
int b=1;
  • 引用即別名:引用不是新定義一個變數,而是給已存在的變數取了一個別名,它和它引用的變數共用同一塊記憶體空間。引用只能繫結物件,而引用本身不是物件,是別名。

  • 引用在定義時必須初始化,而不能先宣告再賦值。而且型別必須嚴格匹配。只能繫結左值而不能繫結。

    int& refa2; refa = 2a;//報錯
    double& dref = a;//報錯
    int& ref10 = 10;//錯誤,10為字面值常量,右值
    string str = "abc"; string &s = str;//正確。字串字面值為左值
    
  • 引用不能重新繫結

&refa1=b;//報錯 lvalue required as left operand of assignment,=的左值是一個常量
  • 一個變數可以有多個引用,同時一個引用也可以繼續引用。

    int& refa2=a;//正確
    int& ref=refa1;//正確。refa1即使a的別名,均會與a進行繫結
    

指標

  1. 語法:資料型別* 指標變數名;

指標是一個變數,儲存另一個變數的記憶體地址。宣告中指標的型別用於指定它所指向物件的型別

int a=1;
int* p1;
p1 = &a;//&作為取址符,p中存放a的地址。因此p是一個指向int的指標
p1 = a;//報錯
double* p2 = &a;//報錯
std::cout<<*p1;//輸出1,解引用符*來訪問指標指向的物件。
*p1 = 2;
std::cout<<a;//輸出2
  1. 指標值總會是下列四種狀態之一:
  • 指向一個物件的地址

  • 指向緊鄰物件所佔空間的下一個位置

  • 空指標,意味著指標沒有指向任何物件。其地址為0,任何程式資料都不會儲存在地址為0的記憶體塊中,它是被作業系統預留的記憶體塊。

    int* p = NULL;
    int* p = nullptr;//優先使用
    int* p = 0;
    std::cout<<p;//輸出0
    
  • 無效指標(野指標),上述情況之外的其他值。未經初始化的指標就是個無效指標,任何一個指標變數在做解地址操作前,都必須保證它指向的是有效的、可用的記憶體塊,否則會出現無法預料的錯誤,而編譯器無法檢查出此類錯誤。所以在定義指標變數的時候一定要進行初始化如果實在是不知道指標的指向,則初始化為空指標。

  1. void* 指標

    void* 可以存放任何型別的地址,而不能訪問其物件

    int a=1;
    void* p = &a;
    std::cout<<p;//正確,輸出a的地址
    std::count<<*p;//報錯 'void*' is not a pointer-to-object type
    
  2. 指向指標的指標

    透過*的個數區分指標的級別,

    int a = 1;
    int* p = &a;
    int** pp = &p;
    
  3. 指向指標的引用

    int i = 1;
    int* p = nullptr;
    int*& r = p;//從右往左讀,&說明r是一個引用,*說明r引用的是一個指標,int說明r引用的指標的型別是int 
    r = &i;//相當於令p指向了i;
    *r = 0;//將i的值改為0;