C++ 使用std::unique\u ptr的双(二维)阵列

C++ 使用std::unique\u ptr的双(二维)阵列,c++,c++11,unique-ptr,C++,C++11,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; } }

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

  // 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;

但是不断收到一个错误,说
no operator=与这些操作数匹配。这里我做错了什么?

您的代码有效地操纵了int数组

<>在C++中,通常需要将它实现为:

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

这不是
唯一性\u ptr
的好例子。此外,您不需要使用指向
unique\u ptr
的指针,也不需要动态分配
unique\u ptr
对象。
unique\u ptr
的全部目的是消除指针的使用,并提供对象的自动分配和解除分配

您不能将
int*
分配给
std::unique\u ptr
,这是导致错误的原因。正确的代码是

      a[i] = std::unique_ptr<int[]>(new int[2]);
所有这些都可以初始化并使用与您已有的代码相同的代码,只是它们更容易构建,并且您不必销毁它们

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

//yo

我能想到的唯一理由是在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调试模式下的标准容器是“选中”的,速度非常慢,这在对大型数据集进行科学编程时可能会很烦人。

如果您没有使用
std::array
std::vector
而不是动态分配的数组,在C++11中,可以对二维数组使用
唯一\u ptr
,如下所示:

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
超出范围时,其自定义deleter lambda函数会在删除行数组之前删除列数组。每个表达式的
都使用了函子。

一个更进一步的例子启发了我这个解决方案

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]);
}
size\u t k=10;
std::unique_ptr y(新int*[k](),
[](int**x){删除[]和(x[0][0]);
删除[]x;});
//分配大数组
y、 get()[0]=newint[k*10];
//建立行指针
用于(行大小=0;行
在这里,所有维度都可以是动态的,您可以将其包装在一个类中并公开一个操作符[]。此外,内存是以连续的方式分配的,您可以很容易地引入一个分配器来分配对齐的内存。

for(i=0;i
#include
for (i=0; i<5; i++)   // deallocation
      delete x[i];
delete x;
#包括
#定义print(x)std::cout当然,
std::unique_ptr(新int[2]);
将有错误的删除器——应该是
std::unique_ptr(新int[2])
.Preemptive+1,假设你能解决这个问题。.-]@ildjarn:我从来没有使用过数组的
uniqueptr
,我对语法很模糊。谢谢!@Evan:确保对任何你觉得有用的答案进行投票(向上箭头在左边),并将其中一个标记为“正确”答案(复选标记就在箭头下方)。感谢您的输入。我理解unique_ptr的方式是确保它指向的实例只有一个引用。因此,使用unique_ptr指向unique_ptr来创建矩阵应该可以使用unique_ptr,因为不会有另一个引用该实例。此外,我不理解最后一句话背后的原因任何RAI类都应该提供相同的唯一保证。大多数C++类是RAII。因此,应该使用正确的工具进行工作。向量和数组应该比UNQuyJPPTHER更好。唯一的PTR的原因主要是保持动态分配的单个对象。我不能立即想到在UNIQ中存储数组的理由。ue_ptr.it有一些很好的使用案例(当然!),因为它是在标准中专门针对的:主模板
unique_ptr
和专业化
unique_ptr
。我猜这不仅仅是为了完整性,因为对于
共享的\u ptr
没有这样的专业化。独特的\u ptr相对于向量的优点是,可以避免初始化,在某些情况下初始化的成本可能会很高。参考,这可以使用
\u mm\u malloc
进行扩展吗?如何使用
\u mm\u malloc
>分配内存并在自定义删除程序中使用
\u mm\u free
。谢谢,我成功了。忘记了你的第二件事,即分配单独的行(没有这一点,我会出现分段错误)。使用可变模板处理示例,在该示例中,我可以创建多维数组,而无需使用
.get()访问数据
“#define println(x)std::cout@blastfurning,其余的,我问了同样的问题,他们给了我这个解决方案,我认为它很有用:)@blastfurning我已经编辑了代码,现在好了吗?
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;
    }
);
for (size_t row = 0; row < 10; ++row) {
    (x.get())[row] = new int[5];
}
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]);
}
for (i=0; i<5; i++)   // deallocation
      delete x[i];
delete x;
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
#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]);
    }
}