C++中變量以及基本類型
內置類型包括:字符,整型,浮點型等;同時C+還支持更加復雜的數(shù)據(jù)類型,首先來看看基本的內置類型;
C++定義的內置類型
- 算數(shù)類型
- 整形:
-
bool
:布爾類型,用于表示真和假; -
char
:字符型,最小尺寸為8
位; -
wchar_t
:表示寬字符,最小尺寸為16
位; -
char16_t
:表示最小尺寸為16
位,Unicode
字符; -
char32_t
:表示最下尺寸為32
位,Unicode
字符; -
short
:表示短整型,最小長度為16
位; -
int
:表示整型,最小尺寸為16
位; -
long
:表示長整型,最小尺寸為32
位; -
long long
:長整型,最小尺寸為64
位; -
float
:單精度浮點數(shù),6
位有效數(shù)字; -
double
:雙精度浮點型,10
為有效數(shù)字; -
long double
:擴展精度浮點型,10
位有效數(shù)字;
-
-
C++
中對于長度的規(guī)定:一個int
至少和一個short
一樣大,一個long
至少
和一個int
一樣大,一個long long
至少和一個long
一樣大,其中long long
類型是C++11
標準中定
義的; - 整型按照不同的標準還可以劃分成為帶符號整型(用于表示正數(shù),負數(shù),0),無符號類型(只能用于表示正數(shù)),
默認的都是帶符號的,可以通過unsigned
來表示無符號類型; - 類型轉換
類型所能表示的范圍決定了轉換的過程
非布爾類型的算數(shù)值賦值給布爾類型時,初始值為
0
,賦值結果為false
,否則結果為true
;如果講上面的過程反過來進行賦值,初始值為
false
結果為0
,初始值為true
結果為1
;如果將一個浮點數(shù)據(jù)賦值給整數(shù)類型時,結果僅僅保留浮點數(shù)據(jù)的整數(shù)部分;
整數(shù)賦值為浮點數(shù)據(jù)類型時,小數(shù)部分為0,,如果整數(shù)的類型超過了浮點類型,精度就會有所損失;
如果將一個大范圍的數(shù),賦值給一個小范圍的類型,賦值后的結果是進行取余操作;
- 整形:
#include <iostream>
using namespace std;
int main(){
bool bi = 10;
bool by = 0;
cout << "one is "<< bi << " Next one is " << by << endl;
int i ;
i = 3.14;
cout << "The i(int) is "<< i << endl;
double dx ;
dx = 1;
cout << "The dx(double) is " << dx << endl;
unsigned char cx = -1;
cout << "Unsigned char(cx) is " << (int)cx << endl;
unsigned char cy = 256;
cout << "Unsigned char(cy) is " << (int)cy << endl;
}
字面值常量
每個字面值常量都對應一種數(shù)據(jù)類型,字面值常量的形式和值決定了它的數(shù)據(jù)類型;
- 整型和浮點型
字面值包括十進制,八進制,十六進制等形式,用0
開始代表八進制,使用0x
或者0X
開頭代表十六進制;對
于整型字面值常量的具體數(shù)據(jù)類型由它的值和符號來決定; - 字符和字符串型
使用''包含的單個字符稱為char
字面值,使用""包含的0個或者多個字符稱為字符串字面值;字符串字面值
通常表示的是由常量字符構成的數(shù)組,編譯器會在每個字符串的結尾使用\0
,字符'A'
表示的是單個字符
但是"A"
表示的是兩個字符'A'和\0
;對于編譯器來說,如果存在兩個字符串字面值之間僅僅由空格,縮進,
和換行符分離,name本質上就是一個整體; - 常用的轉移序列
- 程序員不能夠直接使用的字符包含以下兩種:
- 1 不可打印字符,比如退格符號,換行符號;
- 2 在C++語言中由特殊定義的符號:單引號,雙引號,問號,反斜線等,這就需要使用轉義序列;
- 程序員不能夠直接使用的字符包含以下兩種:
符號 | 含義 |
---|---|
\n | 換行符,可以用于結束本行輸入,進入下一行,也用來刷新緩存 |
\t | 橫向制表符號,每次縮進有限個單位 |
\v | 表示縱向指標符號,垂直制表符號 |
\b | 表示退格符號,每次回退一格 |
" | 用于打印"" |
\ | 用于轉義\ |
? | 用于轉義? |
' | 用于轉義'' |
\r | 表示回車符號 |
\f | 表示進紙符號 |
以上字符都是被當做一個字符來進行使用的; |
- 指定字面值類型
通過添加前綴或者后綴的方法可以用來改變整形,浮點型和字符型字面值的默認類型;
前綴 | 含義 | 類型 |
---|---|---|
u | Unicode 16字符 | char16_t |
U | Unicode 32字符 | char32_t |
L | 寬字符 | wchar_t |
u8 | UTF-8(僅僅用于字符串字面值常量) | char |
- 整數(shù)型字面值
后綴 | 最小匹配類型 |
---|---|
u or U | unsigned |
l or L | long |
ll or LL | long long |
- *浮點型字符類型
后綴 | 類型 |
---|---|
f or F | float |
l or L | long double |
- 布爾字面值
true
和false
都是布爾類型的字面值;
變量
變量提供一個具名的,可供程序操作的存儲空間,數(shù)據(jù)類型決定著變量所占內存空間的大小和布局方式該空間能
存儲值的范圍,以及變量能夠參與的運算;
-
定義變量
int sum1,sum2;
:首先是類型名,然后是變量列表,最后是;
結尾;- 對象:對象表示的是一塊能夠存儲數(shù)據(jù)并且具有某種類型的內存空間;
- 對象可以表示類中;
- 通常已經(jīng)命名的對象成為變量;
- 對象還用于表示能夠被程序修改的數(shù)據(jù),值通常用來表示只讀的數(shù)據(jù);
- 還是將對象理解為某種數(shù)據(jù)類型的內存空間;
- 對象:對象表示的是一塊能夠存儲數(shù)據(jù)并且具有某種類型的內存空間;
-
初始化和賦值操作
- 初始化:對象在創(chuàng)建時獲得的某個特定的值;在變量的初始化過程中,在一條語句中可以用一個已經(jīng)初始化
的變量去為另一個要定義的變量進行初始化操作; - 賦值操作:表示的是將對象的當前值擦除,用一個新的值來進行代替;
初始化的四種方式
int i1 = 0; int i2 = {0}; int i3(0); int i4{0};
- 默認初始化操作:如果定義變量時,沒有指定初始值,變量會執(zhí)行默認初始化,默認值由變量類型來決定;如果
內置類型的變量未被初始化,定義于任何函數(shù)值外的變量會被初始化為0,定義域函數(shù)體內部的內置類型的變
量將不會被初始化,如果訪問此類未被初始化的內置類型數(shù)據(jù)會發(fā)生錯誤;
在類里面可以各自決定其初始化對象的方式,并且是否允許不初始化就定義對象,也有類本身決定; - 當時用列表數(shù)初始化時枪眉,初始數(shù)值存在丟失的風險,編譯器回進行報錯;
- 初始化:對象在創(chuàng)建時獲得的某個特定的值;在變量的初始化過程中,在一條語句中可以用一個已經(jīng)初始化
-
聲明和定義的關系:
- 在
C++
語言中為了支持分離式編譯帖努,通常將聲明和函數(shù)的定義分開帮碰; - 聲明使得名字為人所知,聲明使用
extern
比如extern int i
笨使,表示的含義是僅僅是聲明了這個變量美澳,但是不能夠顯式的初始化這個變量; - 定義負責創(chuàng)建和名字關聯(lián)的實體眠饮;
- 變量只能夠被定義一次奥帘,但是可以被聲明很多次;
- 如果
extern
包含初始值就變成了定義;
總結: - 也就是當變量的定義前面有關鍵字
extern
時,并且沒有進行變量的初始化賦值,就是變量的聲明; -
C++
語言是一種靜態(tài)類型的語言,也就是說,在編譯階段段進行類型檢查;
- 在
-
標識符
組成:C++
語言的標識符,必須由字母.數(shù)字和下劃線組成,并且必須由字母或者下劃線開頭,標識付沒有長度限制;注意:
* 用戶自定義的標識符不能夠出現(xiàn)兩個連續(xù)的下劃線;
* 同時也不能夠使用下劃線緊跟大寫字母開頭;- 變量的命名規(guī)范
- 標識符需要體現(xiàn)特定的意義
- 變量名稱一般使用小寫;
- 用戶自定義的類名一般使用大寫字母開頭;
- 如果標識符有多個單詞組成,單詞之間應該又明顯的區(qū)分;
C++
關鍵字一共有:5*13+8=73
關鍵字;
- 變量的命名規(guī)范
-
作用域
作用域表示的是大部分是使用{}
進行分割的,并且作用域是可以進行嵌套的,當某個作用域中定義了變量,那么在其嵌套的的作用
域中都是可以訪問該變量的;- 一個建議就是局部變量盡量不要和全局變量沖突;
-
復合類型
- 引用
引用可以分為左值引用和右值引用;- 左值引用:引用就是個對象起了另外一個名字.并且引用必須被初始化,且不能夠修改引用的值,也就是說引用無法綁定一個
新的對象;對于引用的操作等價于對于引用對象的操作;
- 左值引用:引用就是個對象起了另外一個名字.并且引用必須被初始化,且不能夠修改引用的值,也就是說引用無法綁定一個
- 指針
和引用的不同:
* 指針本身就是一個對象,允許對于指針進行賦值和拷貝,在指針的生命周期內,可以指向幾個不同對象;
* 指針不需要在定義時,就進行賦值;
指針存放的是某個單元的地址,引用只是一個別名,并沒有地址,所以不能夠定義指向引用的指針
如果這樣定義int ival = 1024; int *p = &ival;
但是這樣其實也是可行,書里面說的不能夠定義指向引用的指針,上面的代碼都是沒有任何錯誤的的;int inval = 1024; int &rival = ival; int *p = rival;
指針是一個地址,獲取地址使用&
運算符; - 當存在指針時,指針的四種指向:
- 指針指向一個對象;
- 指向緊鄰對象所占空間的的下一個位置;
- 空指針,也就是指向
NULL
; - 無效指針,也就是指向其他情況;
- 解引用
如果需要利用指針來訪問對象,就需要使用解引用符號*
;
需要說明的是借用操作僅僅適合于那些真正指向某個對象的有效地址的指針; - 空指針的初始化
int *pival1 = nullptr; int *pival2 = 0; int *pival3 = NULL; //這里需要#include<cstdlib>
nullptr
:是字面值,這個是C++11
引用的新標準,是一種特殊的字面值,可以被轉換成任意的指針類型;
建議使用這種方式進行控制真的初始化;書里面給出的一點建議:初始化所有定義的指針;-
void *
指針
void *
類型的指針可以用于存放任意對象的地址,所以不確定是什么類型的時候,建議聲明成這種類型; - 指針與引用的區(qū)別
- 引用本身不是一個對象,但是指針是一個對象,所以引用是可以指向指針的;
int i = 42; int *p; int *&r = p;
- 引用
-
const
限定符- 當定義某一個值,并且希望這個值不被改變時.可以使用
const
限定符; - 需要注意的是
const
定義時,就需要進行初始化,如果執(zhí)行了默認初始化,之后值就不能夠進行更改; - 如果利用一個對象來初始化另一個對象,那么兩個對象是不是
const
并沒有太多的要求; - 在默認情況下,
const
對象僅僅在文件內部有效;如果多個文件之間需要共享const
文件,那么需要使用關鍵字extern
;
- 當定義某一個值,并且希望這個值不被改變時.可以使用
-
const
與引用- 當引用和
const
進行綁定時,對常量的引用不能夠用來修改所綁定的對象; - 當對象是一個
const
常量時,那么引用也必須是一個const
常量;
const int ci = 1024; const int &rci = ci; int &r2 = ci; //因為`ci`是一個`const`常量,所以引用必須是`const`常量,所以這里會出錯;
-
const
引用通常稱為"常量引用"; - 引用的類型必須和所引用對象的類型一致,但是例外的情況有兩種:
- 初始化常量引用時,允許用任意表達式作為初始值;
int i = 42; const int &r1 = i; const int &r2 = 42; int &r4 = r1; //這個操作就是錯誤的,`r4`是一個非常量的引用;
- 對
const
的引用可能引用一個非const
的值;-
const int& i2 = i
,其中i
不一定是一個常量值;因為const
引用并不要求i
為常量,但是反過來,當i
為常量,對i
的引用必須是const
常量引用;
-
- 當引用和
-
const
和指針- 當
pi
是一個常量時,pi
的指針也必須是一個常量
const double pi = 3.14; const double* cptr = π
- 當
-
一點小總結:
- 指向常量的指針或者引用,只不過是指針或者常量以為自己指向了常量,而不去修改常量的值,但是實際上,這些值往往
是可以改變; - 指針允許定義為常量,但是常量指針必須進行初始化;
int *const ptr=&tr
;
- 指向常量的指針或者引用,只不過是指針或者常量以為自己指向了常量,而不去修改常量的值,但是實際上,這些值往往
-
頂層
const
與底層const
- 這里涉及兩個問題,首先:指針是常量還是指針所指向的對象是個常量,頂層
const
表示的是指針本身是一個常量,爾底層const
用于表示指針所指向的對象是一個常量; - 另一方面來說頂層
const
用于表示任意的對象是常量,但是底層的const
用于表示指針和引用某些部分是常量; - 指針類型可以表示頂層也可以表示底層;
-
const int *const pintq = &intq
:對于這個來說最左邊的const
表示底層,右邊的const
表示頂層; - 用于聲明引用的都是底層
const
; - 這些區(qū)別在進行對象拷貝是區(qū)別明顯;
- 這里涉及兩個問題,首先:指針是常量還是指針所指向的對象是個常量,頂層
-
常量表達式
- 用于表示在程序的便以階段就得到結果的表達式,常見的包括
const
初始化的對象,字面值常量; - 所以
const int size = get_size()
,這個就不是常量表達式;size
的值只有等到程序運行時才可以的得到; -
C++11
允許將一個可能是常量表達式生命為constexpr
,讓編譯器進行檢查;
- 用于表示在程序的便以階段就得到結果的表達式,常見的包括
-
字面值常量
- 算數(shù)類型,引用和指針都屬于字面值類型,其中指針被定義為
constexpr
時,初始值必須是nullptr
或者是0,或者是某個固定
地址里面的對象; - 函數(shù)體里面的變量一般存放于非固定的位置,所以不能夠使用
constexpr
,但是所有函數(shù)體外的變量則例外; - 如果再
consexpr
聲明時,定義了一個指針,那么該限定符僅對指針有效和指針所指向的對象無關;
- 算數(shù)類型,引用和指針都屬于字面值類型,其中指針被定義為
-
類型處理
兩種辦法:* `typedef oldname newname` * `using newname = oldname`; * 定以后的別名和原來的名稱完全等價,但是在理解替換后的別名時,是不能夠替換回去的,這樣產(chǎn)生的理解是錯誤的; * 例如:`typedef char* pstring; const pstring cstr = 0; const pstring *ps;` * 對于替換之后的解釋,首先應該解釋變量本身的類型,`cstr`是一個沒有類型的,其次解釋`pstring`的含義,是一個常量指 針,所以`cstr`是一個指向`char`的常量指針;對于`ps`,首先是一個指針類型,其次它的對象是一個指向`char`的常量指針; * 如果進行替換就會影響`const`和`*`的相對位置,從而理解含義就會發(fā)生變換;
-
auto
類型說明符-
auto
通過初始值來推斷變量的類型.所以使用auto
時,必須包含初始值,如果連續(xù)進行賦值操作,那么類型必須是匹配的; - 對于引用來說,編譯器使用應用對象的類型作為
auto
的類型; -
auto
會忽略頂層的const
,但是會保留底層const
;但是可以通過添加const
來保留頂層const
;這是對于指針來說; - 當設置為一個引用的
auto
時,初始值中頂層的const
仍然有效; - 在一條語句中定義多個變量時,符號
&
和*
不屬于基本數(shù)據(jù)類型;
-
-
decltype
類型指示符需要通過表達式的類型來定義自己需要的類型,但是有不對表達式進行變量的初始化;
decltype(f()) sum = x;
編譯器可以通過分析返回值f
的類型得到sum
的類型,而不需要對x
進行類型的判定;decltype
,如果使用的表達式是一個變量,那么decltype
返回該變量的類型(包括頂層的const
和引用);引用一直是引用對象的同義詞,但是在
decltype
是一個例外;const int& cj = 0;decltype(cj) = ci;
在這里cj
是一個const int&
的引用,但是和引用本身的對象沒有關系,只和類
型有關;如果
decltype(*p)
,如果進行解引用操作,那么得到的就是一個引用類型,并且引用類型必須有初始值;int i; decltype((i));decltype(i);
,前者得到是int&
類型,后者得到的是int
類型;(())
:表示的一定是引用;類里面的數(shù)據(jù)成員,在定義對象之后,每個對象都有數(shù)據(jù)的一份拷貝,數(shù)據(jù)之間是不會相互影響的;