2014-04-03 86 views
1

假設在C++中,我有以下代碼:分配給動態數組時,內存是否在C++中分配?

class Foo { 
private: 
    double* myData; 
public: 
    Foo(double data[]) { 
     myData = data; 
    } 
} 

int main() { 
    double mainData[] = {1.0}; 
    Foo myfoo(mainData); 
} 

據我所知可以告訴,當傳遞到Foo構造mainData被視爲一個指針,所以行myData = data只分配指針地址。所以沒有額外的內存分配在這裏,對嗎?但是,Foo類負責提供一個析構函數來釋放myData的內存?或者我們有一個實際指向堆棧內存的動態數組指針嗎?

另外,如果我要保護FoomyData從當mainData改變不斷變化,有一個簡單的辦法迫使Foo構造複製呢?理想情況下,myData將是一個簡單的數組,不是指針,但將行double* myData更改爲double myData[]似乎不起作用,因爲直到運行時數組的大小才知道。

+2

這類問題導致C++中出現很多錯誤。在您的程序中擁有明確的數據所有權策略非常重要。如果你想'Foo'擁有它的數據,用'std :: vector '替換'myData',並根據需要填充它。或者,如果大小在編譯時是固定的,那麼'double myData [SIZE]'。 – japreiss

回答

3

這裏的參數不是一個動態數組:

Foo(double data[]) 

事實上聲明等效於這樣的:

Foo(double * data) 

即使decltype會告訴你,他們是同樣的事情,而且這兩個簽名將作爲重載發生衝突。

因此,沒有分配。您只傳遞一個指向數組的第一個元素的指針。

另外,C++自動複製數組的唯一地方是它是類的成員,並且不允許成員使用不確定大小的空括號[]語法。 (或者,如果是,則大小已經由類類型齊全,生成的拷貝構造函數或賦值操作符之前的時間確定的。)

另外,如果我要保護Foo的myData的更改時mainData被改變了,有沒有一種簡單的方法來強制Foo的構造函數來複制它?理想情況下,myData將是一個簡單的數組,而不是指針,但將行double * myData更改爲double myData []似乎不起作用,因爲數組的大小在運行時纔是未知的。

您可以保留一份數據,但是如果在編譯時其大小(或者至少是一個上限)未知,您將需要一個指針。我會建議通過裸指針std::vector,或至少std::unique_ptr<double[]>

0

是的,它不分配額外的內存。

不,如果沒有被告知,那麼析構函數將不會對類字段做任何事情。

1
  1. 指針只保留存儲地址,而不newdelete涉及指針無關與分配或釋放。因此你的代碼不會調用任何內存分配。
  2. 爲了刪除你必須做的(動態分配)陣列delete[] foo;
  3. 只有動態分配的對象必須被刪除,如果你的類取得所有權(其管理的陣列,調用銷燬刪除)傳遞一個陣列自動存儲時間是一個非常糟糕的主意。
0

在Foo類實例中將有指向由其他類分配/管理的數據的指針,這是非常糟糕的設計。最好的做法是讓Foo構造函數創建一個副本並將其存儲在指針中。然後在desctructor釋放那一個。這需要將數組的長度傳遞給Foo構造函數。我希望有所幫助。

2

在這種情況下,myData指向堆棧中的一個地址,當函數超出作用域時,它會調用Foo的析構函數。通常,當您使用關鍵字new分配它們時,數組被描述爲動態的。

至於你的第二個問題,你可能將不得不傳遞給構造函數一個指向數組的指針和數組的長度。然後您需要使用傳入的長度動態創建一個雙數組(由myData指向),然後創建一個副本。

不要忘記在析構函數中刪除內存。