18

我有一个由指针分配的双数组。

  // 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。我在这里做错了什么?

4

8 回答 8

23

您不能将 a 分配int*给 a std::unique_ptr<int[]>,这就是您的错误的原因。正确的代码是

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

unique_ptr但是, piokuc 是正确的,将它用于数组是非常不寻常的,因为这就是它的用途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<int, 2>> container1(5); 
//make a 5x2 automatic array, can't resize the 2 or 5 but is _really fast_.
std::array<std::array<int, 2>, 5> container;

所有这些都可以像你已经拥有的代码一样被初始化和使用,除了它们更容易构建,而且你不必销毁它们。

于 2012-03-20T23:11:12.973 回答
7

如果您没有使用 astd::array或 astd::vector代替动态分配数组的奢侈,您可以unique_ptr在 C++11 中将 a 用于二维数组,如下所示:

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 循环分配列数组:

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

unique_ptr超出范围时,其自定义删除器 lambda 函数负责在删除行数组之前删除列数组。该for_each表达式使用default_delete函子。

于 2015-02-23T20:21:15.640 回答
3
for (i=0; i<5; i++)   // deallocation
      delete x[i];
  delete x;

不不不不

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

//哟

于 2012-03-20T23:38:33.407 回答
2

我能想到在 std::vector 上使用 std::unique_ptr (或者说 boost::scoped_array )来保存数组的唯一原因通常是不适用的......

1)它节省了 1 或 2 个指针的内存,具体取决于您是否知道所有数组的大小 [无关紧要,除非您有大量非常小的数组]

2) 如果您只是将数组传递给需要 C 样式数组或原始指针的函数,它可能感觉更自然。虽然 std::vector 保证在顺序存储上,所以传递(a.empty() ? nullptr : &a[0], a.size())给这样的函数也是 100% 合法的。

3) MSVC 调试模式下的标准容器默认被“检查”并且非常慢,这在对大型数据集进行科学编程时可能会很烦人。

于 2013-02-25T01:12:39.010 回答
2

您的代码有效地操作了一个 int 数组的数组。

在 C++ 中,您通常希望将其实现为:

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

这对unique_ptr. 此外,您不需要使用指针来动态unique_ptr分配unique_ptr对象。整个要点unique_ptr是消除指针的使用并提供对象的自动分配和释放。

于 2012-03-20T20:24:08.413 回答
2
#include <iostream>
#include <memory>

#define print(x) std::cout << x
#define println(x) std::cout << x << std::endl

int main() {
    std::unique_ptr<std::unique_ptr<int[]>[]> arr(new std::unique_ptr<int[]>[2]());
    for (int i = 0; i < 2; i++)
    {
        arr[i] = std::make_unique<int[]>(5);
        for (int j = 0; j < 5; j++) {
            arr[i][j] = j;
            println(arr[i][j]);
        }
        println(arr[i]);
    }
}
于 2020-08-12T21:09:43.220 回答
0
for (i=0; i<5; i++)   // deallocation
      delete x[i];
delete x;

这是一个常见的错误。x[i] 是一个数组,因此您必须先使用 delete[] 删除每个数组,然后您可以使用 delete[] 删除 int* 数组

正确的解除分配将是:

for (i=0; i<5; i++)   
      delete[] x[i]; //desallocate each array of int
delete[] x; //desallocate your array of int*
x = nullptr; //good practice to be sure it wont cause any dmg
于 2018-09-11T19:38:29.603 回答
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]);
}

这里所有维度都可以是动态的,您可以将其包装在一个类中并公开一个运算符[]。此外,内存是以连续方式分配的,您可以轻松引入分配器,它分配对齐的内存。

于 2016-10-13T18:28:37.090 回答