我有一个指针分配给指针的双数组。
// 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
。我在这里做错了什么?
答案 0 :(得分:16)
您无法将int*
分配给std::unique_ptr<int[]>
,这是导致错误的原因。正确的代码是
a[i] = std::unique_ptr<int[]>(new int[2]);
然而,piokuc是正确的,使用unique_ptr
对数组是非常不寻常的,因为std::vector
和std::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 :(得分:5)
如果您没有使用std::array
或std::vector
而不是动态分配的数组,可以在C +中使用unique_ptr
作为二维数组+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循环然后分配列数组:
for (size_t row = 0; row < 10; ++row) {
(x.get())[row] = new int[5];
}
当unique_ptr
超出范围时,其自定义删除器lambda函数会在删除行数组之前删除列数组。 for_each
表达式使用default_delete仿函数。
答案 2 :(得分:2)
您的代码正在有效地操作int数组数组。
在C ++中,您通常希望将其实现为:
std::vector<std::vector<int> > x;
这对unique_ptr来说不是一个好例子。此外,您不需要使用指向unique_ptr的指针并动态分配unique_ptr对象。 unique_ptr的重点是消除指针的使用并提供对象的自动分配和释放。
答案 3 :(得分:2)
for (i=0; i<5; i++) // deallocation
delete x[i];
delete x;
否否否
delete [] x[i];
delete [] x;
//哟
答案 4 :(得分:1)
我可以想到使用std :: unique_ptr(或者说boost :: scoped_array)而不是std :: vector来保存数组的唯一原因通常是不适用的......
1)它可以节省1或2个指针的内存,具体取决于你是否知道所有数组的大小[不相关,除非你有大量非常小的数组]
2)如果你只是将数组传递给一个需要C样式数组或原始指针的函数,它可能感觉更自然。 std :: vector IS保证在顺序存储上,所以将(a.empty() ? nullptr : &a[0], a.size())
传递给这样的函数也是100%合法的。
3)默认情况下,MSVC调试模式下的标准容器被“检查”并且非常慢,这对于在大型数据集上进行科学编程时可能会很烦人。
答案 5 :(得分:1)
#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]);
}
}
答案 6 :(得分: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]);
}
这里所有维度都可以是动态的,你可以将它包装在一个类中并公开一个operator []。内存也以连续的方式分配,您可以轻松引入分配器,分配对齐的内存。
答案 7 :(得分: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