2012-03-20 150 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]); 
} 

这里所有的尺寸可以是动态的,你可以用它在类的内部和公开的操作[]。此外,内存以连续的方式分配,您可以轻松引入分配器,分配对齐的内存。