c++ primer 第五版學習筆記-第二章 變數和基本型別
本文為轉載,出處:https://blog.csdn.net/libin1105/article/details/48157115
https://blog.csdn.net/sunhero2010/article/details/49621299
2.1 基本內建型別
內建型別包括算術型別和布林型別。
1.算術型別分為兩類:整型(integral type,包括字元和布林型別在內)和浮點型。
布林型別(bool)的取值是真(true)或者假(false)。
2.除去布林型和擴充套件的字元型之外,其他整型可以劃分為帶符號的(signed)和無符號的(unsigned)兩種。帶符號型別可以表示正數、負數或0,無符號型別則僅能表示大於等於0的值。
型別int、short、long和long long都是帶符號的,通過在這些型別名前新增unsigned就可以得到無符號型別,例如unsigned long。型別unsigned int可以縮寫為unsigned。
與其他整型不同,字元型被分為了三種:char、signed char和unsigned char。特別需要注意的是:型別char和型別signed char並不一樣。儘管字元型有三種,但是字元的表現形式卻只有兩種:帶符號的和無符號的。型別char實際上會表現為上述兩種形式中的一種,具體是哪種由編譯器決定。
3.unsigned也能接收負值,不過會自動將這個負值轉化為正值。signed 轉 unsigned超出範圍時會進行取模賦值,如將 -1 賦值給unsigned char型別的變數,則最後的賦值結果是:-1 % 2^sizeof(unsigned char)
例如,8位元大小的unsigned char可以表示0-255區間內的值,如果我們賦予了一個區間以外的值,則實際結果是該值對256取模後的餘數,結果是255.
4.以0開頭的數代表八進位制,以0x開頭的數表示十六進位制。
5.由單引號括起來的一個字元稱為char型字面值,雙引號括起來的零個或多個字元則構成字串型字面值。
6.轉義字元
換行符 \n 橫向製表符 \t 報警(響鈴)符 \a 縱向製表符 \v 退格浮 \b 雙引號 \" 反斜線 \\ 問號 \? 單引號 \' 回車符 \r 進紙符 \
如果反斜線\後面跟著的八位數字超過3個,只有前3個數字與\構成轉義序列,例如\1234表示2個字元,但是\x要用到後面跟著的所有數字。
7.指定字面值的型別
8.字面值常量
一個形如42的值被稱作字面值常量。每個字面值常量都對應一種資料型別,字面值常量的值和形式決定了它的型別。
2.2 變數
1.變數定義的基本形式是:首先是型別說明符(type specifier),隨後緊跟由一個或多個變數名組成的列表,其中變數名以逗號分隔,最後以分號結束。列表中每個變數名的型別都由型別說明符指定,定義時還可以為一個或多個變數賦初值。變數定義的形式:型別 變數名1, 變數名2;
2.物件是指一塊能儲存資料並具有某種型別的記憶體空間。
3.初始化不是賦值,初始化的含義是建立變數時賦予其一個初始值,而賦值的含義是把物件的當前值擦除,而以一個新值來替代。
4.作為C++11新標準的一部分,用花括號來初始化變數得到了全面應用,而在此之前,這種初始化的形式僅在某些受限的場合下才能使用。這種初始化的形式被稱為列表初始化(list initialization)。現在,無論是初始化物件還是某些時候為物件賦新值,都可以使用這樣一組由花括號括起來的初始值了。
(1)大括號初始化
int a=0,b={0},c(0),d{0}
- 1
對於b,d用{ }初始化,當初始值存在丟失精度風險時,編譯器報錯。
(2)預設初始化
定義於任何函式體之外的變數初始為0,函式體內值未定義。
5.
6.變數命名規範
變數命名有許多約定俗成的規範,下面的這些規範能有效提高程式的可讀性:
- 識別符號要能體現實際含義。
- 變數名一般用小寫字母,如index,不要使用Index或INDEX。
- 使用者自定義的類名一般以大寫字母開頭,如Sales_item。
- 如果識別符號由多個單片語成,則單詞間應有明顯區分,如student_loan或studentLoan,不要使用studentloan。
- 變數名由字母,下劃線,數字組成,以字母或下劃線開頭,不能連續兩個下劃線,不能下劃線連大寫字母開頭,函式體外定義不能下劃線開頭。
7.變數定義時如果沒有初始化,則會被預設初始:
- 函式體外的變數會被初始化為0
- 函式體內的未初始化的變數則不會被預設初始化
- 未被初始化的內建型別變數的值是未定義的
- 類的物件如果沒有顯示地初始化,則其值由類確定
- 如果試圖拷貝或以其他形式訪問未定義的值,則會引發錯誤
8.c++支援分離式編譯機制,允許將程式分割為若干個檔案,每個檔案可被獨立編譯。為了支援這個機制,c++將宣告和定義區分開來。
9.宣告和定義
- 宣告使名字為程式所知,一個檔案如果想使用別處定義的名字,則必須包含對那個名字的宣告。
- 宣告規定了變數的型別和名字,這點和定義是相同的,但是僅宣告一個變數的話需要在變數名前加上關鍵字extern,而且不要顯示地初始化變數。
- 定義負責建立和名字關聯的實體、還會申請儲存空間,也可能會為變數賦初始值
- 變數只能被定義一次,但是可以被宣告多次
- 任何包含了顯示初始化的宣告會變成定義,不管是否加了extern
- 在函式體內部初始化一個由extern標記了的變數將會引發錯誤 e.g.
extern int i; // 宣告i而非定義 i int j; // 宣告並定義 j
externint i;//宣告存在int,但不申請儲存空間,可以多次重複宣告。
externint i=10;//函式體外,相當於定義;函式體內,引發錯誤。
10.作用域
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int reused = 42; // 全域性作用域
int main()
{
// 塊作用域,宣告週期到main函式結束為止
int unique = 0;
// 使用的是全域性作用域中的reused
cout << reused << " " << unique << endl;
// 定義一個塊作用域內的變數reused,覆蓋掉全域性作用域中的同名變數
int reused = 0;
// 使用的是塊作用域中的reused
cout << reused << " " << unique << endl;
// 顯示地訪問全域性作用域中的reused,因為全域性作用域本身沒有名字,所以作用域操作符的左側為空時,向全域性作用域發起請求
cout << ::reused << " " << unique << endl;
return 0;
}
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int reused = 42; // 全域性作用域
int main()
{
// 塊作用域,宣告週期到main函式結束為止
int unique = 0;
// 使用的是全域性作用域中的reused
cout << reused << " " << unique << endl;
// 定義一個塊作用域內的變數reused,覆蓋掉全域性作用域中的同名變數
int reused = 0;
// 使用的是塊作用域中的reused
cout << reused << " " << unique << endl;
// 顯示地訪問全域性作用域中的reused
cout << ::reused << " " << unique << endl;
return 0;
}
2.3 複合型別
1.引用並非物件,相反的,它只是為一個已經存在的物件所起的另外一個名字。
int a=2; int &b=a;
- 引用不是物件,只是一個已經存在的物件的別名,所以不能定義引用的引用
- 引用必須被初始化,且初始值必須是一個物件(非字面值,常量引用可以使用字面值初始化),初始化之後無法被重新與其他的物件進行繫結 例如:int &a=10;//錯誤,引用型別的初始值必須是一個物件; double a=3.14;int &b=a;//錯誤,此處引用型別的初始值必須是int
- 給引用賦值實際上是給引用繫結的物件賦值 :double d=0,&r2=d;r2=3.1415;//正確,相當於把3.1415給了d。
- 一般情況下引用的型別需要與繫結的物件的型別一致,兩種例外情況如下:
- 引用的型別與物件的型別存在繼承關係:SubClass sub; Parent &p1 = sub;
- 引用的型別與物件的型別含有一個可接受的const型別轉換規則:
/**
* 下面的程式碼編譯器會將其優化為:
* double dval = 3.14;
* const int temp = dval;
* const int &ri = temp;
* 實際使用中避免這種情況。
*/
double dval = 3.14;
const int &ri = dval;
2.指標值
指標的值(即地址)應屬下列4種狀態之一:
1.指向一個物件。
2.指向緊鄰物件所佔空間的下一個位置。
3.空指標,意味著指標沒有指向任何物件。
4.無效指標,也就是上述情況之外的其他值。
指標,建議初始化所有的指標
- 指標本身是一個物件,允許指標賦值和拷貝
- 指標不要求在定義時就初始化 //這兩個是指標和引用的區別。
- 函式體內的指標未初始化時的值也是未定義的
- 指標存放的是指定物件的地址,獲取物件的地址可以使用取地址符 &
- 一般情況下引用的型別需要與繫結的物件的型別一致,兩種例外情況與引用的相同
- 無效指標(野指標):值是未定義的指標
- 空指標:沒有指向任何物件的指標,生成空指標的方法:
int *p = nullptr;
int *p = 0;
// #include cstdlib
int *p = NULL;
3.當用到一個預處理變數時,前處理器會自動地將它替換為實際值,因此用NULL初始化指標和用0初始化指標是一樣的。在新標準下,現在的C++程式最好使用nullptr,同時儘量避免使用NULL。
4.指標和引用都能提供對其他物件的間接訪問,然而在具體實現細節上二者有很大不同,其中最重要的一點就是引用本身並非一個物件。一旦定義了引用,就無法令其再繫結到另外的物件,之後每次使用這個引用都是訪問它最初繫結的那個物件。
5.void*是一種特殊的指標型別,可用於存放任意物件的地址。一個void*指標存放著一個地址,這一點和其他指標類似。
6.一般來說,宣告符中修飾符的個數並沒有限制。當有多個修飾符連寫在一起時,按照其邏輯關係詳加解釋即可。以指標為例,指標是記憶體中的物件,像其他物件一樣也有自己的地址,因此允許把指標的地址再存放到另一個指標當中。
通過*的個數可以區分指標的級別。也就是說,**表示指向指標的指標,***表示指向指標的指標的指標,以此類推。
7.引用本身不是一個物件,因此不能定義指向引用的指標。但指標是物件,所以存在對指標的引用。
8.通過解引用符 * 來利用指標訪問物件,給解引用的結果賦值等價於給指標所指的物件賦值。
9.指向指標的引用:int *&r;
2.4 const限定符
1.const物件一旦建立後其值就不能再改變,所以const物件必須初始化。一如既往,初始值可以是任意複雜的表示式。
2.如果想在多個檔案之間共享const物件,必須在變數的定義之前新增extern關鍵字。
//主檔案
extern const int bufSize=512;//定義const
//其他檔案
extern const int bufSize;//引用bufSize=512
3.指標本身是一個物件,它又可以指向另外一個物件。因此,指標本身是不是常量以及指標所指的是不是一個常量就是兩個相互獨立的問題。用名詞頂層const(top-level const)表示指標本身是個常量,而用名詞底層const(low-level const)表示指標所指的物件是一個常量。
4.頂層const可以表示任意的物件是常量,這一點對任何資料型別都適用,如算術型別、類、指標等。底層const則與指標和引用等複合型別的基本型別部分有關。比較特殊的是,指標型別既可以是頂層const也可以是底層const,這一點和其他型別相比區別明顯。
注:把*放在const之前用以說明指標是一個常量,也就是說不變的是指標本身的值,並非指向的那個值。
int i = 0;
int *const p1 = &i; // 不能改變p1的值,這是一個頂層const
const int ci = 42; // 不能改變ci的值,這是一個頂層const
const int *p2 = &ci; // 允許改變p2的值,這是一個底層const
const int *const p3 = p2; // 靠右的const是頂層const,靠左的是底層const
const int &r = ci; // 用於宣告引用的const都是底層const
當執行拷貝操作時候,頂層的const不受影響,拷入和拷出的物件是否是常量都無所謂,但是底層const在拷貝時候,拷入和拷出的物件必須具有相同的底層const資格,或者兩個物件的資料型別必須能夠轉換,一般來說,非常量可以轉換成常量,反之不行。
int *p=p3; //錯誤:p3包含底層const的定義,但是p沒有
p2=p3; //正確:p2,p3都是底層const
p2=&i; //正確:int*能夠轉換成const int*
int &r=ci; // 錯誤:普通的int&不能繫結到int常量上
const int &r2=i; //正確:const int&可以繫結到一個普通int上
5.常量表達式(const expression)是指值不會改變並且在編譯過程就能得到計算結果的表示式。
常量表達式要求:資料型別是常量,且初始值在編譯過程中能得到計算結果。
6.C++11新標準規定,允許將變數宣告為constexpr型別以便由編譯器來驗證變數的值是否是一個常量表達式。宣告為constexpr的變數一定是一個常量,而且必須用常量表達式初始化。
constexpr int mf=20;
constexpr int limit=mf+1;
constexpr int sz=size();//當size()是一個constexpr函式時正確
7.常量引用可以指向常量引用與非常量引用,但是非常量引用不能指向常量引用,常量引用不能重新賦值,常量引用可以使用字面值進行初始化
常量指標可以指向常量物件與非常量物件,但是非常量指標不能指向常量物件,常量指標可以重新賦值,但是不能通過常量指標修改其指向的物件
常量指標必須初始化,比如:
int *const p1 = &i;
8.常量表達式的值需要在編譯時就得到計算,因此對宣告constexpr時用到的型別必須有所限制。因為這些型別一般比較簡單,值也顯而易見、容易得到,就把它們稱為"字面值型別"(literal type)。
算術型別、引用和指標都屬於字面值型別。自定義類scales_item、IO庫、string型別不屬於字面值型別,不能被定義為constexpr。
一個constexpr指標的初始值必須是nullptr或者是0,或者是儲存於某個固定地址中的物件。
constexpr既可以指向常量又可以指向非常量。
2.5 處理型別
1.類型別名(type alias)是一個名字,它是某種型別的同義詞。使用類型別名有很多好處,它讓複雜的型別名字變得簡單明瞭、易於理解和使用,還有助於程式設計師清楚地知道使用該型別的真實目的。
有兩種方法可用於定義類型別名。傳統的方法是使用關鍵字typedef:
typedef double wages; //wages是double的同義詞
typedef wages base, *p; //base是double的同義詞,p是double*的同義詞
新標準規定了一種新的方法,使用別名宣告(alias declaration)來定義型別的別名:using SI = Sales_item; // SI是Sales_item的同義詞
2.auto型別- auto i = 1; 編譯器會自動分析推斷 i 的型別
- auto定義的變數必須要初始化
- auto在一條語句上宣告多個變數時,該語句的所有變數的初始基本資料型別都必須一樣:auto i = 0, b = 1;
#include <iostream>
int main()
{
const int i = 1;
// j 是int,並不是const int
auto j = i;
// k 是const int
const auto k = j;
// m 是const int*,而不是int*
auto m = &i;
// n 是const int&,而不是int&
auto &n = i;
return 0;
}
①引用其實是使用引用的物件,當引用作為初始值時候,其實真正參與初始化的是引用物件的值,此時以引用物件的型別作為auto的型別:
int i=0,&r=i;
auto a=r;//a為int
②auto一般忽略頂層const,同時底層const會保留
const int ci=i,&cr=ci;
auto b=ci; //b為int(ci的頂層const被忽略)
auto c=cr; //c為int(cr是ci別名,ci是頂層const)
auto d=&i;//d為int*(int的地址就是指向int的指標)
auto e=&ci; //e為const int*(對常量取地址是一種底層const)
③若希望auto是頂層const,需明確指出:const auto f=ci; //c為int f為const Int④auto &g=ci; //g為const int&
3.decltype,它的作用是選擇並返回運算元的資料型別。在此過程中,編譯器分析表示式並得到它的型別,卻不實際計算表示式的值。
如果decltype使用的表示式是一個變數,則他返回變數的型別。如果decltype使用的表示式不是一個變數,則他返回表示式結果對應的型別。但是不實際計算該表示式。
//decltype完美複製了頂層const與引用
const int ci=0,&cj=ci;
decltype(ci) x=0;//const int x=0;
decltype(cj) y=x;//const int &y=x;
decltype(cj) z;//錯誤,引用未初始化
decltype(cj+0) z;//正確,等價於int z;
//對於" (變數名) "的形式
int i,j;
decltype((i)) d=j;//int &d=j;
賦值會產生引用,引用的型別就是左值的型別,也就是說如果i是int,則表示式i=x的型別是int&.4.decltype((variable))(注意是雙層括號)的結果永遠是引用,而decltype(variable)結果只有當variable本身就是一個引用時才是引用。decltype((i)) d=j;//int &d=j;
2.6 自定義資料結構
1.我們的類以關鍵字struct開始,緊跟著類名和類體(其中類體部分可以為空)。類體由花括號包圍形成了一個新的作用域)。類內部定義的名字必須唯一,但是可以與類外部定義的名字重複。
struct A {
// 類體
} variable1, variable2;
// 等價於:
struct A {
// 類體
};
A variable1, variable2;
c++11為類內成員進行預設初始化:struct edge{int u=10,v;}E;//u==10,v==0
2.確保標頭檔案多次包含仍能安全工作的常用技術是前處理器(preprocessor),它由C++語言從C語言繼承而來。前處理器是在編譯之前執行的一段程式,可以部分地改變我們所寫的程式。之前已經用到了一項預處理功能#include,當前處理器看到#include標記時就會用指定的標頭檔案的內容代替#include。
3.C++程式還會用到的一項預處理功能是標頭檔案保護符(header guard),標頭檔案保護符依賴於預處理變數(參見2.3.2節,第53頁)。預處理變數有兩種狀態:已定義和未定義。#define指令把一個名字設定為預處理變數,另外兩個指令則分別檢查某個指定的預處理變數是否已經定義:#ifdef當且僅當變數已定義時為真,#ifndef當且僅當變數未定義時為真。一旦檢查結果為真,則執行後續操作直至遇到#endif指令為止。
檔案頭保護符:#ifndef-#endif,#ifdef-#endif,無視作用域的規則,必須唯一
#define DEBUG
//將DEBUG設定為預處理變數,至#undef 或整個程式結束,無視作用域規則
#ifdef DEBUG
//DEBUG為預處理變數時為真,執行語句至#endif
#endif
#undef DEBUG
//釋放DEBUG定義
#ifndef DEBUG
//DEBUG為非預處理變數時為真,執行語句至#endif
#endif
相關推薦
c++ primer 第五版學習筆記-第二章 變數和基本型別
本文為轉載,出處:https://blog.csdn.net/libin1105/article/details/48157115 https://blog.csdn.net/sunhero2010/article/d
C++Primer第五版 習題答案 第二章 變數和基本型別(variables and basic types)
2.1 C++語言規定一個int至少和一個short一樣大,一個long至少和一個int一樣大,一個long long至少和一個long一樣大。每個的最小尺寸分別為:short,16位;int,16位;long,32位;long long,64位。 除去布林
C++ primer學習筆記——第二章 變數和基本型別
一、基本內建型別 C++基本內建型別包括算術型別和空型別。 1.算術型別 算術型別分為兩類:整形(包括字元和布林型在內)和浮點型 bool(布林型) 長度(位元組):1 取值範圍:false,true
c++ primer第五版----學習筆記(十九)Ⅱ
部分習題解答: 19.1、19.2: #include <iostream> #include <cstdlib> using namespace std; void *operator new(size_t size) { cout << "new(
c++ primer第五版----學習筆記(十九)Ⅰ
文章目錄 ==特殊工具與技術== 1.控制記憶體分配 1.1 過載new和delete 1.2 定位new表示式 2. 執行時型別識別 2.1 dynamic_cast運算子 2.2 typeid運算子
c++primer第五版----學習筆記(十八)Ⅱ
部分習題解答: 18.1: (a)range_error (b)exception 如果寫成throw p,則丟擲指標,是錯誤的18.2: 發生異常,所在塊之前的臨時變數都會被銷燬,v呼叫vector類的解構函式進行銷燬,並釋放相關記憶體;p指標會被銷燬,但p指向的記憶體是動態分配的,所以該記憶
c++ primer第五版----學習筆記(十八)Ⅰ
用於大型程式的工具:異常處理、名稱空間和多重繼承 特殊要求: 在獨立開發的子系統之間協同處理錯誤的能力 使用各種庫(可能包含獨立開發的庫)進行協同開發的能力 對比較複雜的應用概念建模的能力 1.異常處理: 異常處理機制允許程式中獨立開發的部分能夠在執行
c++ primer第五版----學習筆記(十三)Ⅰ
知識點: 拷貝控制操作:拷貝、移動、賦值和銷燬 在定義一個類時,我們可以顯式或隱式的定義在此型別的物件拷貝、賦值、移動、銷燬是做什麼,主要通過五種特殊的成員函式來完成這些操作:拷貝建構函式、拷貝複製運算子、移動建構函式、移動複製運算子和解構函式 1.拷貝建構函式: 定
c++ primer第五版----學習筆記(十五)Ⅰ
oop的核心思想是多型性。我們把具有繼承關係的多個型別稱為多型型別; 引用或指標的靜態型別與動態型別不同這一事實正是c++語言支援多型性的根本存在 當且僅當對通過指標或引用呼叫虛擬函式時,才會在執行時解析該呼叫,也只有在這種情況下物件的動態型別才有可能與靜態型別不同 一個派生類的函式如果覆蓋了某個繼承而來
c++ primer第五版----學習筆記(十六)Ⅱ
部分習題解答: 16.1: 當呼叫template時,編譯器使用實參的型別來確定繫結到模板引數T的型別,之後編譯器利用推斷出的模板引數來例項化一個特定版本的函式 16.2: #ifndef COMPARE_H #define COMPARE_H template &
c++ primer第五版----學習筆記(五)
1.空語句:最簡單的語句,只包含一個單獨的分號 複合語句:指用花括號括起來的語句和宣告的序列,複合語句也被稱為塊 2.if語句: //語法形式: if (condition) statement //if、else語句 if (condition) s
c++ primer 第五版學習筆記-第七章 類
本文為轉載,出處:https://blog.csdn.net/libin1105/article/details/48664019 https://blog.csdn.net/sunhero2010/article
c++ primer 第五版學習筆記-第三章 字串、向量和陣列
本文為轉載,出處:https://blog.csdn.net/libin1105/article/details/48210261 https://blog.csdn.net/fnoi2014xtx/article/
C++ Primer 第五版 讀書筆記 第一章 開始
下面是C++ Primer第一章的讀書筆記 ———————————————————————— 0001.作業系統如何執行C++程式 作業系統通過呼叫main來執行C++程式 0002.main 作業系統執行一個C++程式時所呼叫的函式 每個程式必須有且只有一個命名為mai
《C++ Primer》讀書筆記-第二章 變數和基本型別
第一篇文章寫完後收到了很多同學的後臺留言,有鼓勵的,也有提出建議的,還有說錯別字的,每一條都一一回復了,當然提出建議的大都是說排版問題,現在已經換到MarkDown編輯器了,大家湊合著看就行了,肯定不影響閱讀了,至於錯別字的,哈哈,你懂就行。 &nbs
c++ primer 筆記第二章變數和基本型別(二)
2.4 const限定符 const定義的變數不能改變,因此const變數必須初始化。可以使用表示式初始化。 預設狀態下const物件僅在檔案內有效。 可以在宣告和定義都加extern。 練習2.26 (a) 不合法,未初始化 (b) 合法 (c) 合法 (d) 不合
C++ Primer中文版(第五版)--第二章 變數和基本型別
資料型別是程式的基礎,它告訴我們資料的意義以及我們能在資料上執行的操作 C++定義了幾種基本內建型別:字元、整型、浮點數等,同時程式設計師可以自定義資料型別,另外C++ 標準庫還定義了一些更加複雜的資料型別,如可變長字串和向量。 2.1 基本內建型別
C++Primer第五版【筆記】——第九章——順序容器
1. 順序容器概述 表一中的順序容器,提供了對元素快速的順序訪問。但是其他操作的開銷則不同: 新增或刪除元素的開銷進行非順序訪問的開銷 表一:順序容器型別 vector 可變長度陣列。支援快速隨機訪問。在非尾部插入或刪除元素速度很慢 deque 雙端佇列。
C++ Primer 【第四版】第二章 變數和基本型別
習題2.1 int、long 和short 型別之間有什麼差別? 【解答】 它們的最小儲存空間不同,分別為16 位、32 位和16 位。一般而言,short 型別為半個機器字(word)長,int 型別為一個機器字長,而long 型別為一個或兩個機器字長(在32 位機器
LuceneInAction(第2版)學習筆記——第二章 構建索引
1. 文件和域 1.1.文件和域的關係 文件是Lucene索引和搜尋的原子單位。 文件為包含一個或多個域的容器,而域則依次包含“真正的”被搜尋內容。 每個域都有一個標識名稱,該名稱為一個文字值或二進位制值。 將一個文件加入到索引中時,可以通過一系列選項來控制Luc