2012-03-20 149 views
8

我有一個由指向指針的指針分配的double數組。使用std :: unique_ptr的雙(二維)數組

// pointer to pointer 
    int **x = new int *[5]; // allocation 
    for (i=0; i<5; i++){ 
     x[i] = new int[2]; 
    } 

    for (i=0; i<5; i++){  // assignment 
     for (j=0; j<2; j++){ 
      x[i][j] = i+j; 
     } 
    } 

    for (i=0; i<5; i++) // deallocation 
     delete x[i]; 
    delete x; 

我試圖做到這一點使用unique_ptr

std::unique_ptr<std::unique_ptr<int>[]> a(new std::unique_ptr<int>[5]); 
    for (i=0; i<5; i++) 
     a[i] = new int[2]; 

,但一直得到一個錯誤,指出no operator = matches these operands。我在這裏做錯了什麼?

回答

2

你的代碼正在有效地處理int數組的數組。

在C++中,你通常會想實現它:

std::vector<std::vector<int> > x; 

這不是的unique_ptr一個很好的例子。另外,您不應該使用指向unique_ptr的指針並動態分配unique_ptr對象。 unique_ptr的全部要點是消除指針的使用並提供對象的自動分配和釋放。

+0

謝謝您的輸入。我理解unique_ptr的方式是確保它指向的實例只有1個引用。所以使用unique_ptr指向一個unique_ptr來創建一個矩陣應該可以使用unique_ptr,因爲不會有對該實例的另一個引用。另外,我不明白最後一句話背後的原因。謝謝。 – Evan 2012-03-21 14:15:02

+0

任何RAII類應提供相同的獨特保證。大多數C++類都是RAII。所以你應該使用正確的工具來完成這項工作。 vector和array應該優先於unique_ptr。 – 2012-03-21 15:14:04

+0

唯一ptrs的原因主要是保存動態分配的單個對象。我不能馬上想到在unique_ptr中存儲數組的原因。 – 2012-03-21 15:16:16

15

您不能將int*分配給std::unique_ptr<int[]>,這是導致錯誤的原因。正確的代碼是

 a[i] = std::unique_ptr<int[]>(new int[2]); 

然而,piokuc是正確的,這是極不尋常的使用unique_ptr的陣列,這就是std::vectorstd::array是,根據是否有大小提前知道。

//make a 5x2 dynamic jagged array, 100% resizable any time 
std::vector<std::vector<int>> container1(5, std::vector<int>(2)); 
//make a 5x2 dynamic rectangular array, can resize the 5 but not the 2 
std::vector<std::array<2, int>> container1(5); 
//make a 5x2 automatic array, can't resize the 2 or 5 but is _really fast_. 
std::array<5, std::array<2, int>> container; 

所有這些都可以被初始化,使用一樣的,你已經有代碼,但它們更容易構建,而你沒有摧毀他們。

+1

當然,'std :: unique_ptr (new int [2]);'將會有錯誤的刪除器 - 應該是'std :: unique_ptr (new int [2]);'。搶先+1假設你會解決這個問題。 ; - ] – ildjarn 2012-03-20 23:26:04

+0

@ildjarn:我從來沒有使用'unique_ptr'數組,我對語法很模糊。謝謝! – 2012-03-20 23:31:52

+0

感謝您的意見! – Evan 2012-03-21 14:46:50

2
for (i=0; i<5; i++) // deallocation 
     delete x[i]; 
    delete x; 

否否否否

delete [] x[i]; 
delete [] x; 

//喲

1

我能想到的使用std ::的unique_ptr(或說的boost :: scoped_array)在性病的唯一原因::保存數組的矢量通常不適用...

1)它可以節省1或2個指針的內存,這取決於你是否知道所有數組的大小是[不相關的,除非你擁有大量的數組SMA 2)如果你只是將數組傳遞給某個需要C風格數組或原始指針的函數,它可能覺得自然更合適。 std :: vector保證在順序存儲上,所以傳遞(a.empty() ? nullptr : &a[0], a.size())到這樣的函數也是100%合法的。 3)默認情況下,MSVC調試模式下的標準容器被「檢查」,速度非常慢,這在對大型數據集進行科學編程時可能令人討厭。

+0

unique_ptr 優於矢量的優點是您可以避免初始化,其成本在某些情況下可能很重要。參考http://stackoverflow.com/questions/96579/stl-vectors-with-uninitialized-storage和http://stackoverflow.com/questions/7546620/operator-new-initializes-memory-to-zero – goertzenator 2013-08-27 14:29:16

4

如果沒有使用std::arraystd::vector代替動態分配的數組的奢侈品,你可以使用一個unique_ptr在C++ 11的二維陣列如下:

std::unique_ptr<int*, std::function<void(int**)>> x(
    new int*[10](), 
    [](int** x) { 
     std::for_each(x, x + 10, std::default_delete<int[]>()); 
     delete[] x; 
    } 
); 

unique_ptr聲明負責分配數組的維數。 new int*[10]()後面的()確保每個列指針初始化爲nullptr

一種用於環路,則分配該柱陣列:

for (size_t row = 0; row < 10; ++row) { 
    (x.get())[row] = new int[5]; 
} 

unique_ptr超出範圍,其定製刪除的λ函數採用刪除行陣列之前刪除列陣列的護理。 for_each表達式使用default_delete函子。

+0

這可能是使用'_mm_malloc'擴展以及如何? – 2016-10-13 17:02:44

+0

使用'__mm_malloc'分配內存並在自定義刪除程序中使用'_mm_free'。 – sakra 2016-10-13 18:09:37

+0

謝謝,我得到了這個工作。忘記第二部分,即分配各行(沒有這個,我得到了分段錯誤)。使用可變參數模板處理一個示例,我可以在其中創建多維數組,而無需使用'.get()'訪問數據。 – 2016-10-13 18:13:44

0

一個示例還了啓發了我對這個解決方案

size_t k = 10; 
std::unique_ptr<int*, std::function<void(int**)>> y(new int*[k](), 
    [](int** x) {delete [] &(x[0][0]); 
       delete[] x;}); 

// Allocate the large array 
y.get()[0] = new int[k*10]; 

// Establish row-pointers 
for (size_t row = 0; row < k; ++row) { 
    (y.get())[row] = &(y.get()[0][0]); 
} 

這裏所有的尺寸可以是動態的,你可以用它在類的內部和公開的操作[]。此外,內存以連續的方式分配,您可以輕鬆引入分配器,分配對齊的內存。