數組(array)是一種數據格式,可以存儲多個同類型的值。每一個值都存儲在一個獨立的數組元素中,計算機在內存中依次存儲數組的各個元素。ios
數組聲明的三個特色:git
C++中能夠經過修改簡單變量的聲明,添加中括號(其中包含元素數目)來完成數組聲明。github
例如:編程
short days[24]; // 一天有24個小時
聲明數組的的通常語法格式爲:數組
// 數組類型 數組名字[數組的大小] int score[4]; // 四我的的分數,整型數組
數組的大小是指定元素的數目
,必須是整型常數或const值
,也能夠是常量表達式(8*sizeof(int))安全
可使用其餘的類型來建立(C語言使用術語:派生類型
)數據結構
數組的用途,能夠單獨訪問數組元素,方法是:使用下標
或索引
對元素進行編號。從0開始編號
。函數
編譯器不會檢查下標是否有效,因此要注意下標合法性,避免程序異常問題。
C++使用索引的方括號表示法來指定數組元素。工具
1.只有在定義數組時才能初始化,此後不能使用,也不能將一個數值賦給另外一個數組。學習
2.初始化數組時,提供的值少於數組的元素數目。
3.若是隻對數組的一部分進行初始化,則編譯器把其餘元素設置爲0。
4.若是初始化爲{1}
而不是{0}
,則第一個元素被設置爲1,其餘元素都被設置爲0.
5.若是初始化數組方括號內([])
爲空,C++編譯器將計算元素個數
。 例如:short things[] = {1,3,5,7};
C++11將使用大括號的初始化(列表初始化)
做爲一種通用的初始化方式,可用於全部類型。
在C++中列表初始化就增長了一些功能:
等號(=)
double earnings[4] {1.2e4,1.6e4,1.1e4,1.7e4};
unsigned int const[10] = {}; float balances[100] {};
long num[] = {25,92,3.0}; // 浮點數轉換爲整型是縮窄操做
例子:
#include<iostream> using namespace std; int main() { // 建立一個名字爲yams的數組,包含了3個元素,編號是0~2. int yams[3]; yams[0] = 7; yams[1] = 8; yams[2] = 6; // 使用逗號分隔的值列表(初始化列表),而後用花括號括起來便可。 // 列表中的空格是可選的,若是沒有初始化函數中定義的數組,其元素值也是不肯定。 int yamcosts[3] = {1,2,3}; cout<<"yams 數組是:"<<yams[0]+yams[1]+yams[2]<<endl; cout<<"yams[1] = "<<yams[1]<<endl; int total = yams[0] * yamcosts[0] + yams[1] * yamcosts[1]; total = total + yams[2] * yamcosts[2]; cout<<"total yam = "<<total<<endl; // sizeof運算符返回類型或數據對象的長度(單位爲字節)。 // 若是將sizeof運算符用於數組名,獲得的是整個數組的字節數。 // 若是sizeof用於數組元素,獲得的是元素的長度(單位爲字節)。 cout<<"\n yams數組的大小 = "<<sizeof(yams)<<" Bytes.\n"; cout<<"一個元素的大小 = "<<sizeof(yams[0])<<" Bytes.\n"; return 0; }
字符串是存儲在內存的連續字節中的一系列字符。
C-風格字符串(C-style String)
以空字符(\0,ASCII碼對應爲0)來標記字符串的結尾。
存儲在連續字節
中的一系列字符意味着能夠將字符串
存儲在char數組
中。其中每一個字符都位於本身的數組元素中。
使用引號
括起來的字符串,這種字符串叫 字符串常量(String constant)
或 字符串字面值(string literal)
。
字符串常量(使用雙引號)不能與字符常量(使用單引號)互換。
例如:
char name[] = "Soler";
字符串結尾的空字符
,不用直接顯式包括
,機器在鍵盤輸入,將字符串讀入到char類型
中,會在結尾自動加上空字符
。
⚠️注意:肯定了存儲字符串所需的最短數組時,不要忘記把結尾的空字符
包括在內。
方法:直接兩個引號括起來的字符串合併爲一個。任何兩個由空白(空格、製表符和換行符)
分隔的字符串常量都將自動拼接成一個。
cout<<"My name is " "Soler HO.\n"
將字符串存儲到數組的經常使用方法:
#include <iostream> #include <cstring> /*提供strlen()函數*/ using namespace std; const int Size = 15; int main() { char name1[Size]; char name2[Size] = "C++owboy"; // 字符串的拼接 cout<<"Howdy!I'm "<< name2; cout<<"!,What's your name?\n"; cin>>name1; cout<<"Well, "<<name1<<",your name has : "<<strlen(name1)<<" letters and is stored!\n" ; cout<<"In an array of "<<sizeof(name1)<<" Bytes\n"; cout<<"Your iniatial is "<<name1[0]<<".\n"; // name1數組中的第一個元素 name2[3] = '\0'; cout<<"Here are the first 3 characters of my name:"<<name2<<endl; return 0; }
strlen() 函數
和 sizeof()運算符
的區別
strlen()
函數
存儲在數組中的字符串的長度
,而~~不是數組自己的長度~~
。可見的字符
,而sizeof()
運算符
變量
或數據類型
的字節大小
。類、結構、共用體和其餘用戶自定義數據類型
的大小。解決沒有逐行讀取輸入的缺陷。
istream中提供了面向行的類成員函數:getline()
和 get()
函數
getline()
使用經過回車鍵輸入的換行符來肯定輸入結尾。使用 cin.getline()
。
函數有兩個參數:
數組名稱
。空字符(\0)
)。格式:
cin.getline(name,ArSize);
get()
與getline()
函數相似,接受的參數相同
,解釋參數的方式也相同,並讀到行尾
。
區別:get()
讀取並丟棄
換行符,將其留在輸入隊列中。
格式:
cin.get(name,ArSize);
get() 將兩個類成員函數拼接(合併):
cin.get(name,ArSize).get();
⚠️注意:get() 函數讀取空行後設置會失效,輸入會被阻斷。可用以下恢復:
cin.clear();
混合輸入數字和麪向行的字符串會致使的問題:沒法輸入地址。
解決方法:直接使用get()進行讀取以前丟棄換行符。
string類
位於名稱空間std
中,因此須要提供using指令
或者是直接使用std::string
進行引用。
要使用string類
,必須在程序中包含頭文件string
中。
string類定義隱藏了字符串的數組性質。
使用string對象的方式和使用字符數組相同。
C-風格字符串
來初始化string對象中。cin來將鍵盤輸入
存儲到string對象中。cout
來顯示string對象。數組表示方法
來訪問存儲在string1對象中的字符。賦值 —— 不能將一個數組賦給另外一個數組,但能夠將一個string對象賦另外一個string對象。
char char01[20]; // 建立一個空列表 char char02[20] = "Jason"; // 建立一個初始化數組 string str01; // 建立一個空的string對象 string str02 = "Soler Ho"; // 建立一個初始化的string對象 char01 = char01; // 不可執行,一個數組不能賦值給另外一個數組 str01 = str02; // 可執行,可將一個string對象賦給另外一個string對象。
string類簡化字符串合併操做。
運算符 +
將兩個string對象合併起來。string str01; string str02 = "Soler Ho"; string = str01 + str02;
運算符 +=
將字符串附加
到string對象的末尾
。string str01; string str02 = "Soler Ho"; str01 += str02;
結構是用戶定義
的類型,而結構聲明定義了類型的數據屬性
。
定義類型以後,就直接建立類型的變量。
結構比數組靈活,同一個結構中能夠存儲多種類型的數據。
定義結構描述 —— 描述並標記可以存儲在結構中的各類數據類型
按描述建立結構變量(結構數據對象)。
struct(關鍵字) 類型名(標記成爲新類型的名稱) { 結構成員1; 結構成員2; 結構成員3; };//(結束結構聲明)
對於結構中的成員,使用成員運算符(.)
來進行訪問各個成員。
等號(=)無關緊要
。infor Soler_infor {"Soler HO",55,168}; // 在C++11中,= 號能夠省略
infor Soler_infor {};
✅ 小Tips:C++容許在聲明結構變量時省略關鍵字struct。
成員賦值(memberwise assignment):可使用賦值運算符(=)
將結構賦另外一個同類型的結構。這樣結構中的每一個成員都將被設置爲另外一個結構中相應成員的值。即便成員是數組。這種方式就是成員賦值
。
共用體(union),也叫作聯合(union)
。一種 構造數據類型
。
關鍵字:union
聯合(union):將不一樣類型的數據
在一塊兒共同佔用同一段內存
存儲不一樣的數據類型,但只能同時存儲其中的一種類型
示例:
union sample { int int_val; long long_val; double double_val; };
同時存儲int、long和double
。只能存儲int、long和double
三種。匿名共用體(anonymous union)沒有名稱
,其成員將成爲位於相同地址
處的變量。
C++的enum工具提供了另外一種建立符號常量
的方式,能夠代替const,容許定義新類型,但必須有嚴格限制。
使用enum的語法格式與結構的使用相似。
enum color{red,orange,yellow,green,blue,voilet};
enum week{Monday = 1,Tuesday = 2;Wednesday = 3;Thursday = 4};
指定的值必須是整數
。也能夠只顯示定義其中一些枚舉量的值
。
若是第一個變量未初始化,默認爲0。後面沒有被初始化的枚舉量的值將比其前面的枚舉量大1。也能夠建立多個值相同的枚舉量。
enum {zero,null = 0,numero_one,one = 1};
每一個枚舉都有取值範圍的上限,經過強制類型轉換,能夠將取值範圍中的任何整數值賦給枚舉常量,即便這個值不是枚舉值。
對於選擇使用多少空間來存儲枚舉由編譯器
決定。
對於地址顯示結果是十六進制表示法
,由於都是經常描述內存的表示法
。
指針與C++基本原理
面向對象編程和傳統的過程性編程的區別,OOP強調的是運行階段(而不是編譯階段)進行決策。
指針用於存儲值的地址。指針名錶示的是地址。
*運算符
稱爲間接值或解除引用運算符,將其應用於指針,獲得該地址處存儲的值。
指針的聲明必須指定指向的數據的類型
。
int *p_updates;
*p_updates
的類型是int
,因此*運算符
被用於指針
,因此p_updates變量必須是指針。
運算符*兩邊的空格
是可選的。
int *ptr; /*該狀況強調:*ptr是一個int類型的值。*/ int* ptr; /*該狀況強調:int* 是一種類型,指向int的指針。*/
在C++中,int*
是一種複合類型,是指向int的指針
。
double *tax_ptr;
在C++建立指針時,計算機將分配用來存儲地址的內存
,可是不會分配用來存儲指針所指向的數據的內存。
⚠️注意:必定要在對指針應用解除引用運算符(*)
以前,將指針初始化爲一個肯定
的、適當的地址
。
整數能夠加減乘除等運算,而指針
描述的是位置
。
C++語言數字不能做爲地址使用,若是要把數字當地址來使用,應經過強制類型轉換
將數字轉換爲適當的地址類型。
new分配
和delete釋放
內存指針在運行階段
分配未命名的內存以存儲值。而後使用內存來訪問內存。
C語言中,使用 庫函數malloc()來分配內存。C++中使用 ———— new運算符。
須要內存時,直接使用new來請求,這是內存管理數據包的一個方面。
若是使用了delete運算符
,使得在使用完內存後,可以將其歸還給內存池
,這是有效使用內存的關鍵。
使用delete時,後面要加上指向內存塊的指針。
int * ps = new int; // 使用new進行內存分配 ... delete ps; // 使用delete進行內存的釋放
1.使用delete釋放ps的內存,可是不會刪除指針ps自己。
2.只能用delete
來釋放使用new分配的內存
,可是若是是空的指針
使用delete是安全的。
使用delete的關鍵:用於new分配的內存
。不是要使用於new的指針,而是用於new的地址
。
❌警告:不能建立兩個指向同一個內存塊的指針。會增長錯誤地刪除同一個內存塊兩次的可能性。
C++中,建立動態數組,只須要將數組的元素類型
和元素數目
告訴new便可。必須在類型名
後面加上方括號
,其中包含了元素數目。
通用格式:
Type_name *pointer_name = new Type_name[num_element]; //例子 int * psome =new int[10]; // 建立10個int元素的數組
new運算符會返回第一個元素的地址
若是使用完new分配的內存,使用delete進行內存的釋放。
delete [] psome; // 進行內存的釋放
delete和指針直接的方括號告訴程序,應釋放整個數組
,不只僅是指針指向的元素。
delete中的方括號的有無
取決於使用new時的方括號有無
。
對於指針數組的使用,直接能夠按照普通數組的使用便可。
new[]
爲數組
分配內存時,則應使用delete[]
來釋放。實體
分配內存,則應使用delete(沒有方括號)
來釋放。指針和數組基本等價的緣由:指針算術(pointer arithmetic)
和C++ 內部處理數組的方式
。
- 對
整數變量
+ 1,其值
增長1- 對
指針變量
+ 1,增長的量等於它指向的類型的字節數
。
獲取數組地址的兩種方式
double * pw = wages; // 數組名 = 地址 ;將pw聲明爲指向double類型的指針。而後將其初始化爲wages - - - wages數組中第一個元素的地址。 short * ps = &wages[0]; // 使用地址操做;使用地址運算符來將ps指針初始化爲stacks數組的第一個元素。
要聲明指向特定類型的指針,語法格式:
TypeName *pointerName; // 例子 double * pn; // pn 指向一個double類型 char * ps; // ps 指向一個char類型
將內存地址賦給指針。能夠對變量名應用 & 運算符
,來得到被變量名的內存地址
,new運算符返回未命名的內存的地址。
示例:
double * pn; // pn 指向一個double類型 double * pa; // pa 指向一個double類型 char * pc; // pc 指向一個char類型 double bubble = 3.2; pn = &bubble; // 把bubble的地址賦值給 pn pc = new char; // 新建char地址並分配給pc
對指針解除引用意味着得到指針指向的值
。
引用
或間接值運算符(*)
來解除引用。cout<<*pn; *pc = 's';
數組表示法
。多數狀況下,C++將數組名
視爲數組的第一個元素的地址
。
int tacos[10]; // 此時的tacos一樣也是&tacos[0]
C++中容許指針和整數相加
。加1 的結果等於原來的地址值
加上指向的對象佔用的總字節數
。
也能夠將一個指針減去另外一個指針,得到兩個指針的差。獲得一個整數,僅當兩個指針指向同一個數組(也能夠指向超出結尾的一個位置)時,這種狀況會獲得兩個元素的間隔。
使用數組聲明來建立數組時,將採用靜態聯編
,即數組長度在編譯
時設置。
int tacos[10] // 靜態聯編
使用new[]運算符
建立數組時,將採用動態聯編(動態數組)
,即將在運行時爲數組分配空間,其長度爲運行時設置。
使用這類數組後,要使用
delete[]
釋放所佔用的內存。
使用方括號數組表示法
等同於對指針解除引用
。
數組名和指針變量也是同樣。因此對於指針和數組名,既可使用指針表示法
,也可使用數組表示法
。
int * pt = new int [10]; *pt = 5; pt[0] = 6; pt[9] = 5; int coats[10]; *(coats + 4) = 12;
數組名是第一個元素地址
。
若是給cout提供一個字符的地址,則它將從該字符開始打印,直到遇到空字符爲止。
在cout和多數C++表達式中,char數組名
、char指針
以及用引號括起來的字符串常量
都被解釋爲字符串第一個字符的地址
。
不要使用字符串常量或未被初始化的指針來接收輸入。
在字符串讀入程序時,應使用已分配的內存地址。該地址不是數組名,也可使用new初始化過的指針。
strcpy()
接受兩個參數,第一個:目標地址
,第二個:要複製的字符串的地址
。
要肯定目標空間有足夠的空間來存儲副本。
對於在指定結構成員時,句點運算符
和箭頭運算符
的選擇時:
結構名
,則使用句點運算符(.)
。指向結構的指針
,則使用箭頭運算符(->)
。把new用於結構的兩個步驟
要建立結構,須要同時使用結構類型和new。
自動變量
。
只在特定函數被執行時存在。
自動變量時一個局部變量
,做用域爲包含它的代碼塊
。一般存儲在棧
中,遵循後進先出(LIFO)
。
靜態存儲
整個程序執行期間都存在的存儲方式(存在於程序的整個生命週期
)。
動態存儲
內存池(自由存儲空間或堆)用於靜態變量和自動變量,且內存是分開的。
線程存儲(C++11特性)
模板類vector
和array
是數組的替代品。
模板類vector
相似於string
類,也是一種動態數組
。
vector對象
包含在vector頭文件
中。using編譯指令
、using聲明
或std::vector
。語法
來指出它存儲的數據類型
。元素數
。位於名稱空間std
中,與數組同樣,array對象的長度固定
,也使用棧(靜態內存分配)
,而不是自由存儲區
。
頭文件 array。
不管是數組、vector對象仍是array對象,均可使用標準數組表示法
來訪問各個元素。
從地址
可知,array對象和數組存儲在相同的內存區域(即棧)
中,vector對象存儲在自由存儲區域或堆
中。
能夠將一個array對象賦給另外一個array對象,對於數組,必須逐個
元素複製
數據。
Github地址:https://github.com/SolerHo/cpp-Primer-Plus-6e-Notes/blob/master/Chapter04/README.md
第四章 學習筆記完畢,若有大佬在文中發現錯誤,請指出,謝謝