標籤:

為什麼C++的數組必須要指明尺寸大小?

看&<&&>裡面,內置數組類型好像對Size要求很嚴格,書裡面說數組大小必須是常量,作者Stanley.B.Lippman在寫示例代碼時用了常量定義const(const int seq_size = 18),我自己在G++編譯時用了string[]這種寫法也沒通過。看起來內置類型必須要求一個尺寸大小且該size必須靜態不可變。這是為什麼呢?為何如此設計這門語言?有什麼精妙之處嗎?還是說C++語言裡面分靜態大小的數組和動態大小的數組?


你可以用vector&,C++只是不把別的語言的數組也叫數組罷了。


C++ 的類型系統是編譯期的、靜態的。若 C++ 允許如 C99 VLA 的功能,那麼 sizeof()、decltype() ,甚至是 template 參數都可能要支持動態的數組類型,要麼就不容許在這些地方使用 VLA。

如果真的需要類似的功能,大部分編輯器/平台提供非標準的 alloca()(Windows 有 _malloca() 和 _freea()),可在棧上動態分配空間。


過去我一直認為是C++語法不允許編譯器隱式的去進行堆內存分配。

不過如果c++有一天引入了無棧協程或者resumable function,這必然涉及到需要把局部變數往堆上面分配。到那一天破戒的時候,如果允許數組定義的時候長度是變數,然後編譯器負責對這種數組進行RAII分配和回收,就不奇怪了。


1. 系統級語言是一定要有 zero cost 的編譯期分配空間的非變長數組介面的

2. 我理解 int a[5] 是 C array,現代 C++ 請用 std::array,介面更規範,提供了標準的 STL 方法,能跟 algorthm 更好地一起使用,並且沒有無論空間還是時間的任何代價

3. 動態確定長度的數組請用 vector,也就是大部分語言如 Java,Pythob 的數組,O2 效率跟靜態數組幾乎差不多了。如果可以預估長度,善用 resize 和 reserve。不要自己去 new T[n]

4. 為什麼默認的數組是 plain array 而不是 vector,一個是為了兼容 C,另一個是語言的定位問題。比如 Python 也有 array.array,Js 也有 UInt32Array 來應付一些系統級的需求,但這些任務不是這些語言的主要定位,所以內置的就是類 vector 的數組了。

5. 題外話,vector 作為變長數組真的是一個取得很差的名字。。。


不指明尺寸大小就無法開闢內存。無論是在堆上還是棧上,為了實現常數時間的隨機訪問,數組元素都必須線性的分布在一段內存里。

如果想實現動態數組的話,就意味著編譯器必須要插入額外的代碼來實現動態的重分配內存和轉移元素,這會給程序帶來額外的性能損耗。

c++的基本設計理念之一就是不引入任何沒有必要的cost。換言之,程序員不應該(或者儘可能少的)為任何沒有使用的特性承擔性能開銷。

再者,一個可以動態resize/reallocate的數組對於裸內存和指針非常不友好。頻繁的數組操作會導致一個指針很難被固定在原地。這會使得很多複雜的直接操作內存的編程技巧難以實現。

所以通常的實踐都是如果你確定不需要任何動態數組特性,就用原生數組類型。

需要的話用std::vector


還是說C++語言裡面分靜態大小的數組和動態大小的數組?

是的,請使用 std::array 或者 new 或者 malloc 系列(不清真)


這不是C++的優點或者說功能,所以不能直接為這個設計作論證。

當然,也不能說這是C++的缺點或者說BUG。

確切地說,這是C++的優點(計算機工作量小,運算性能高)的代價(編程者工作量大,開發效率低)。

你當然可以實現一個自製的可以隨意變更尺寸的數組,只是當你在所有地方都這樣做時,就和使用更高級的語言編程沒區別了——犧牲性能換取編寫的效率。

我想C++中也很可能已經提供了不需要那麼高效率的使用方便的語法或者標準庫,道理一樣。


不然呢?不指明尺寸大小怎麼去給你分配內存空間呢?

C99是支持VLA,能用變數來指明數組長度,但實際上是一回事,數組的大小在創建的時候也是固定的。

你要知道,C/C++裡面的數組跟更高級語言裡面的數組或者List不是一回事,雖然他們都能用[]下標訪問。C/C++的數組是要跟一塊連續,已知大小,固定的內存空間(而且分配在棧上)對應的,而後者在底層的實現並不是C/C++裡面的數組,而是其他的一些東西,比如動態分配的內存空間(C的話只能malloc/free,C++就用new和delete)或者鏈表,也可能是STL。

而在C++裡面如果想要動態的效果你應該去用STL,比如vector,deque這些。


C++有兩種「數組」。

第一種是array,聲明方式為:

array&<類型,長度&> a;

用途主要是存長度限定或者需要高速運算的內容,比如存世界上所有大洲的名字,只有6個值的哈希臨時數組,或者某人的生日。

另一種是vector,聲明方式為:

vector&<類型&> v;

用途主要是存放長度不定的數據,或者不需要太高性能的場合。

對於字元串,如果不是因為特殊原因要使用array,則可以使用string,聲明方式為:

string s;

string適合數據大部分小於16位元組的場合,或是數據方差較大的場合。但其實string對於其它場合的處理能力也足夠用。

至於自帶的數組b[n],用處有很大的局限,主要用於:

1、隨手寫個簡單的小程序;

2、對性能有非常高的要求;

3、需要使用變長數組和伸縮數組(需要C99支持);

4、編譯器對array支持差。


因為語言比較貼底層,能少開銷就少開銷。

數組肯定是放在內存上,內存是申請/分配出來的,你不知道大小就沒法分配(因為數組要求連續內存,比如a[0]必須和a[1]貼著,不能像鏈表一樣跳著存)。

vector,或如py的list,一般是事先分配一小份內存,不夠用了重新申請,把舊數據移過去,這就有額外開銷了。


編譯可執行文件時,局部變數數組分配棧空間指令是寫死的。你不給一個確定值,就沒法確定這條指令,就沒法完成編譯。

全局變數數組也同理類似,不給確定值,生成文件時不知道給data節區留多大空間,沒法完成編譯。


數組這東西的定義就要求他要有大小吧,有些不用顯示聲明而已


其實很多語言都有靜態數組啊,包括一些現代語言例如golang。


靜態數組只是從c繼承過來的而已,並沒有什麼「精妙之處」,並且原生數組是不推薦使用的。

如果想用靜態數組可以使用std::array,想用動態數組可以使用std::vector,比原生數組功能更豐富而且更安全。

標準庫可以看成語言的一部分,不應該區別對待


c++的數組是函數的局部變數,是靜態分配的.必須在編譯時候確定,動態改變需要後面的程序在內存中相應的移位.沒有必要.Java等其他語言的數組其實是一個對象,在堆內存中動態申請的,與代碼區不是連續的.而且事實上也不能變長,只不過能在運行期間再指定大小.而動態變長一般用的 是線性表


單純說數組,定義一個數組編譯器得知道為你開闢多大的內存(棧上),這個大小是編譯期就必須的知道的,所以要麼你明確提供大小,要麼提供一個初始化列表,讓編譯器自己數。

int a[3]; //3個元素數組

int a[] = {1,2,3}; //3個元素數組

C99標準支持變長數組VLA,可在運行時確定數組大小。


因為數組中的元素在虛擬內存空間中連續,如果不給長度就不知道要分配的大小是多少。

後面的的變數也就不知道這個數組結束的地址在哪,不知道自己應該存在那個地址。

慢慢學,就明白了。


歪個樓,

如果我沒理解錯的話,內置數組是一個class裡面有一個數組變數吧

那java.util.ArrayList中的默認實現的數組的initialCapacity也是一個常量為10.

歪不歪,LOL

沒用過c++,怕被打,匿了


推薦閱讀:

Data Structures公開課聽課筆記-(三)哈希
函數式語言怎樣表示圖呢?
九章演算法 | Yelp/Pocked Gem面試題:前K個最頻繁的元素
九章演算法 | Google 面試題 : 不同的子序列 解法1
R語言數據結構入門實踐筆記

TAG:數據結構 | CC |