<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
上一篇文章我們介紹了C++中的迭代器,這篇文章將會介紹C++中陣列的概念,陣列是一種和vector類似的資料結構,但是其在效能和靈活性上的權衡中選擇了效能而放棄了一定的靈活性,其與vector相同的地方是,它們都是同一型別的物件的容器,也都可以通過下標存取。其不同點是陣列的大小是固定的,所以無法向一個陣列新增元素,也正是因為其大小固定,所以其在執行時有更好的效能。
陣列是一個複合型別,可以通過類似a[d]的形式定義,其中a是陣列名,d是陣列的容量,d必須要大於0,陣列的容量是陣列型別的一部分,其導致陣列容量必須要在編譯時就已知,這要求陣列容量必須是常數表示式,以下提供了陣列宣告的幾種形式:
unsigned cnt = 42; //不是一個常數表示式 constexpr unsigned sz = 42; //是常數表示式 int arr[10]; //宣告一個容量為10的整型陣列 int *parr[sz]; //42個指向整形指標的陣列 string bad[cnt]; //這是個錯誤宣告,因為cnt不是常數表示式
預設情況下,陣列裡面的元素都會被預設初始化。
我們可以通過列表初始化一個陣列,通過這種方式我們在定義時可以忽略陣列的容量,如果我們指定了陣列容量,那麼在列表初始化時初始化的元素數量不能超過設定的容量值,如果少於設定的陣列的數量,沒有指定值的元素會使用預設初始化的值,例子如下:
const unsigned sz = 3; int a1[sz] = {0, 1, 2}; int a2[] = {0, 1, 2}; //可以忽略陣列的容量 int a3[5] = {0, 1, 2}; //等價於{0, 1, 2, 0, 0} string a4[3] = {"hi", "bye"}; //等價於{"hi", "bye", ""} int a5[2] = {0, 1, 2}; //錯誤
字元陣列有一個額外的初始化方式,就是可以通過一個字元還去初始化字元陣列,但是需要注意的是string是以null字元結尾的,所以在定義陣列容量時要考慮null字元:
char a1[] = "C++"; //其等價於{'C', '+', '+', ' '} char a2[6] = "Daniel" //錯誤,其未考慮到null字元
❝需要注意的是一些編譯器是不支援陣列的拷貝,如果直接通過一個陣列去初始化另一個陣列可能會報錯❞
正如vector,array也可以容納所有的型別,例如指標的陣列,由於陣列是一個物件,所以可以定義指向陣列的指標和參照,,定義指向陣列的指標或者參照可以通過以下方式:
int *ptre[10]; //ptre是一個陣列,其中的元素是10個指向整型的指標 int (*parray)[10] = &arr; //parray是一個指標,其指向的物件是一個容量為10的整型陣列 int (&arrRef)[10] = arr; //arrRef是一個參照,其指向的是一個容量為10的整型陣列
❝在理解宣告時可以按照從左到右,從內到外的順序。❞
在C++中指標和陣列關係是很近的,一般來說,當我們使用一個陣列,編譯器會自動將其轉化為一個指標,一般來說我們是通過地址操作符來獲取一個物件的指標的,但是對於陣列而言,當我們使用陣列時,編譯器將會自動獲取一個指標指向陣列的第一個元素:
string nums = {"one", "two", three}; string *p = &nums[0]; //p指向nums的第一個元素 string *p2 = nums //等價於string *p = &nums[0];
❝在大多數表示式中,我們使用陣列物件,我們其實是獲取一個指標指向陣列的第一個元素❞
由於這個影響,我們對於陣列的操作其實絕大多數都是對於指標的操作,其中一個比較明顯的是當我們使用auto和陣列去初始化一個變數時,其實是宣告了一個指標而不是陣列:
int ia[] = {0, 1, 2, 3, 4}; auto ia2(ia); //ia2是一個整形指標,指向ia的第一個元素 ia2 = 43 //錯誤,不可以將int賦值給一個指標 auto ia3(&ia[0]) //這樣看起來更清楚,ia3是整型指標
需要注意的是當我們使用之前提到的decltype時不會發生這種轉化, decltype(ia)返回的型別是10個整型的陣列:
decltype(ia) ia3 = {0, 1, 2, 3, 4}; ia3 = p; // 錯誤,不可以將一個整型指標賦值給一個陣列 ia3[4] = i; //正確,可以對陣列的元素賦值
指標也是迭代器,指向陣列元素的指標同樣支援我們之前提到的vector和string中迭代器的操作,例如可以通過自增操作實現從一個元素移動到下一個元素:
int arr[] = [0, 1, 2, 3, 4, 5]; int *p = arr; //現在p指向arr[0] ++p; //現在p指向arr[1]
正如我們可以使用迭代器遍歷vector中的元素,我們也可以使用指標去遍歷陣列中的元素,我們可以通過上面的方式獲取陣列的第一個元素的指標,那麼我們又該如何獲取陣列最後一個元素之後的不存在的元素呢,我們可以通過以下方式:
int *e = &arr[6];
我們只可以獲取最後一個元素的下一個元素的地址
for (int *b = arr; b != e; ++b) cout<< *b<<endl
雖然我們可以通過上述方式獲取陣列的第一個元素的地址和最後一個元素的下一個地址,但是這並不是一個好的方法,在新的規範中已經提供了新的函數begin和end可以獲取陣列的第一個元素的地址和最後一個元素的下一個地址:
int ia[] = {0, 1, 2, 3, 4}; int *beg = begin(ia); int *last = end(ia);
指向陣列元素的指標可以使用我們之前在迭代器的文章中提到的所有的迭代器的操作,當我們使用指標加上或者減去一個整型的值時我們將會獲得一個新的指標,這個指標指向原來陣列元素前或者後幾個位置的元素,具體的位置取決於加或者減的值:
constexpr size_t sz = 5; int arr[sz] = {1, 2, 3, 4, 5}; int *p1 = arr; //等價於*p1 = &arr[0] int *p2 = p1 + 4; //p2指向arr[4]
當我們用陣列加上sz時,編譯器會把arr轉化為指向陣列第一個元素的指標,所以如下p就是指向陣列最後一個元素的下一個元素,如果相加結果超出陣列的範圍則會發生錯誤:
int *p = arr + sz; //小心使用,沒有解除參照 int *p3 = arr + 10; //錯誤,陣列只有5個元素,雖然編譯器可能無法檢測到這個錯誤
和迭代器一樣,兩個指標相減其結果是兩個指標之間的距離,其前提是這兩個指標式同一個陣列中的元素:
auto n = end(arr) - begin(arr);
通過上面的介紹我們已經知道了指標也有算數運算,那麼如何判斷是指標的算術運算還是元素的算術運算呢,可以和之前複雜的指標對應,都是先從括號內部開始:
int ia = {0, 2, 4, 6, 8}; int last = *(ia + 4); //先看括號內,所以這是指標的元素暗,last = ia[4] = 8 int last2 = *ia + 4; //ia指向ia[0], 所以last2 = ia[0] + 4 = 4
我們可以看到陣列其實就是一個指向陣列第一個元素的指標,所以對於陣列的下標操作其實就是對於指標的算數元運算,ia[2]等價於*(ia + 2):
int ia = {0, 2, 4, 6, 8}; int *p = &ia[2]; //p指向ia[2]的指標 int j = p[-2]; p[-2]等價於*(p - 2), 所以j = ia[0]
這篇文章主要講述的是C++陣列相關的內容,更多關於C++ 陣列教學的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45