考慮到這一點:C++數組初始化
typedef struct
{
int x;
int y;
} Coordinate;
Coordinate places[100];
是對自動分配的100個座標存儲器?或者當您初始化數組的每個元素時,它是否一次分配一個?
如果您處理未初始化的數組部分,會發生什麼情況?這是否會觸發錯誤?
考慮到這一點:C++數組初始化
typedef struct
{
int x;
int y;
} Coordinate;
Coordinate places[100];
是對自動分配的100個座標存儲器?或者當您初始化數組的每個元素時,它是否一次分配一個?
如果您處理未初始化的數組部分,會發生什麼情況?這是否會觸發錯誤?
1 /是的,有一個分配。在塊的末尾調用析構函數並解除分配。
2 /使用默認構造函數初始化數組的所有元素(如果沒有默認構造函數,則爲編譯時錯誤)。如果默認構造函數沒有初始化某些東西,那麼如果該對象是數組的一部分或者沒有定義,那麼它是相同的行爲(即,如果它們被讀取會導致未定義行爲的未定義值)
只是爲了澄清。所有的100個對象都是一次分配的(或者在編譯時,如果數組是全局的),並立即調用默認構造函數(或者當程序啓動時,如果數組是全局的)。 根據訪問類型,訪問數組的未初始化部分(而不是越界部分)可能會或可能不會觸發錯誤。我相信標準要求它是未定義的行爲。通常情況下,讀取未初始化的int不會觸發錯誤,而通常會取消引用指針。 – Ari 2010-02-23 14:00:37
第一:是,區域是保留,但其內容是無效的,直到區域被正確初始化
第二:很多事情都可能發生,一個是ACCES違反或沒有,但讓你的系統的誤動作
對第二部分的輕微更正...解決未初始化的數組部分不會導致訪問衝突,因爲內存已分配 - 它可能只是填充垃圾數據,這可能會導致錯誤的行爲。 – 2010-02-23 14:16:26
的內存分配會自動在棧上,所以你必須小心你的陣列有多大。每個操作系統都有不同的堆棧大小,但仍有一定的限制。通常每個線程/進程有少量KB。
當您訪問數組的未初始化成員時,您將讀取先前從另一個堆棧框架或之前存在於該存儲器頁面中的任何垃圾。因此,它被認爲是一個良好的習慣,用memset
或數組初始值設定項來初始化數組。
在你的例子中,所有的實例都是一次分配的 - 所有零到99的項都是有效的。如果你在構造函數中使用了一個類型,那麼將會構造所有的100個類型。
編輯 - 正如其他人所指出的,僅僅因爲它的構建並不意味着任何初始化。 「int」的默認構造函數將其保持原樣(這是您的工作,可以將其初始化爲任何您想要的)。 「struct」的默認構造函數爲其成員調用構造函數。也就是說,構建在這裏沒有多大意義 - 但是內存已經分配並準備好供你使用(初始化和)使用。
第一個未初始化的「數組的一部分」不是數組的一部分 - 它超出了界限。例如...
Coordinate mistake = places [100]; // Above the upper bound
這是「未定義」行爲。您可能會遇到崩潰(某種與處理器相關的內存異常)。您的程序可能會繼續愉快地工作,並不知道它使用了無效的垃圾數據。在上述情況下,由於發生的事情相當明顯,您可能會收到編譯器警告 - 但通常情況並非如此。
如果寫以越界 - 數組索引,你可能會破壞其他變量或你的函數的返回地址,或任何事情,讓你的整個程序的行爲從該點起是未定義。這是最大的安全漏洞和「漏洞利用」類別之一的基礎。
std :: vector是另一種創建數組的方法。它不會立即分配所有項目 - 它是一個允許(並管理)調整大小的動態數組。但是,它不會超出基本的C風格數組。
1)內存分配爲一個連續的塊。 2)如果靜態地實例化(即不是auto
變量),則存儲器應該被初始化爲0,否則它將被初始化並且內容應該是未定義的。訪問這些未定義的值不會觸發任何錯誤,如果您讀取垃圾數據並對其執行操作,行爲將完全由非確定性內容確定,以及您的代碼如何處理它。
如果你想自動初始化,你可以定義一個默認的構造函數。在C++中,結構實際上與類相同(區別在於默認的成員可見性和繼承),並且可以具有成員函數,構造函數和析構函數。
如何保留內存取決於聲明數組聲明的位置。如果它是在全局範圍內聲明的(即在一個函數之外),那麼800個字節(假設一個整數是32位長)可以立即用於整個程序。如果它在函數內部,則這800字節被分配到堆棧上,並且在函數退出時不可訪問。
因此,在問題1中:是的,整個100個座標在與聲明相同的範圍內可用。
問題2:您可以隨時訪問所有100個元素,但其內容將被初始化。因此,立即寫入所有100個索引是安全的,只是在你初始化它們之前不要讀取它們。
如果你想初始化所有這些(說0,0),那麼作出這一聲明,而不是:
struct Coordinate
{
int x;
int y;
Coordinate() : x(0), y(0) { }
};
當然
,在C這隻能++。如果您使用C語言編寫代碼,那麼您無法自動初始化數組中的元素。
在0到99範圍外讀取會導致未定義的行爲。充其量,運行時會檢測到給你一個運行時錯誤。在最壞的情況下,你會破壞內存,直到程序結束後纔會知道錯誤在哪裏。所以要小心,並確保你的指數在界限內。
通常的做法是提供一個訪問數組的函數(不要直接訪問數組),並且您可以執行斷言檢查以測試數組索引。
祝你好運
小提示:如果在全局範圍聲明數組,則即使沒有Coordinate()構造函數,int值也將被初始化爲0。 – MtnViewMark 2010-02-23 14:16:51
也在本地範圍內,但使用「靜態」存儲類,保證了零初始化。 – Clifford 2010-02-24 05:05:55
關於「通用實踐」段落,由於這是C++,因此使用'at()'成員函數而不是'[]'運算符訪問的'std :: vector'類型通常會更好(或至少少C類)解決方案,因爲如果索引超出邊界,它會引發異常。 – Clifford 2010-02-24 05:10:44
基於類型的數組行爲不會有任何差異。 因此,一旦創建數組並且未初始化的變量會包含一些垃圾數據,就會完成內存分配。
要初始化數組的所有元素,可以使用默認構造函數將它們初始化爲需要的值或帶有默認參數的構造函數,其中值可以初始化爲未提供值時所需的值。
例如:
struct Coordinate
{
int x;
int y;
Coordinate (int x1 = 0, int y1 = 0) : x(x1), y(y1) { }
};
這適用於陣列和陣列中的所有值將被initiliazed到零(0)。
,用來初始化基本數據類型的數組的所有元素爲零(0)
int places[100] = { 0 };
沒有驗證它是否工作爲用戶定義的類型,雖然。你可以試試看。
當您聲明位置時,會自動分配內存。如果你超出範圍,你可能會導致分段錯誤。 – Beta 2010-02-23 13:55:07
因爲這是C++標記的,所以你不需要使用C typedef習慣用法。改爲使用'struct Coordinate {...};'。這在C++中定義了一個名爲'Coordinate'的類型。 – Clifford 2010-02-23 14:00:18
@貝塔,這是一個答案,而不是評論。你爲什麼不把它放在答案中? – paxdiablo 2010-02-23 14:01:12