如何制作一个包含 unique_ptrs 的数组?
How to make an array that holds unique_ptrs?
我假设下面的代码是 unique_ptr 数组(也不是我想要的)
std::unique_ptr<int[]> arr;
arr = std::make_unique<int[]> (5);
arr[0] = *new int(1);
delete &arr[0]; // malloc error, want to avoid "delete"
但是,我想要一个包含 unique_ptr 的数组,就像这样...
std::unique_ptr<int> arr2 []; //Error, requires explicit size
arr2 = std::make_unique<int> [5]; //Desirable, does not compile
arr2[0] = std::make_unique<int>(1); //Desirable, does not compile
如何制作 unique_ptr 数组?如果那不可能,那么我该如何处理 malloc 错误?
简短回答:使用向量。它们更容易使用,而且您不必显式分配内存。您还应该使用 typedef 来简化语法。
typedef unique_ptr<int> intPtr;
vector<intPtr> vec;
vec.push_back(make_unique<int>(69));
auto myIntPtr = make_unique<int>(16);
vec.push_back(move(myIntPtr)); // unique ptrs cannot be copied, must be moved
unique_ptr<int[5]> p1; // valid syntax
您想要一个包含 unique_ptr
的数组(如标题中所示),还是一个 unique_ptr
包含一个数组(如您的示例中所示)?
如果unique_ptr
的数组是你想要的,那么
std::vector<std::unique_ptr<int>>
或
std::array<std::unique_ptr<int>, 3>;
(例如)将完成这项工作。
如果 unique_ptr
持有一个数组是你想要的,那么 unique_ptr<int[]>
会起作用(有一个 partial specialisation of unique_ptr
to support it),虽然你不能使用 std::make_unique
并且需要自己给 operator new[]
打电话:
std::unique_ptr<int[]> p{new int[42]};
但是,如果您认为自己需要这个,那么您很可能真正想要的是 std::vector
,我强烈建议您改用它。
std::unique_ptr<int[]> arr;
arr = std::make_unique<int[]> (5);
此时你有一个unique_ptr
到int
的数组。这听起来正是您想要的。
arr[0] = *new int(1);
但这值得商榷。它动态分配单个 int
,将 1 分配给已分配的 int
,然后将已分配的 int
处的值 1 分配到元素 0 处的数组中。已分配的 int
被挂起,没有任何指向它,现在特别难以“删除”。这是内存泄漏。
delete &arr[0]; // malloc error, want to avoid "delete"
如您所见,这是致命的。不是尝试 delete
泄漏的 int
,而是使用指向存储在 unique_ptr
中的数组的指针调用 delete
。最终 unique_ptrwill try to
delete` 数组并失败,因为它已经消失了。
根据评论,OP 打算
std::unique_ptr<int*[]> arr;
arr = std::make_unique<int*[]> (5);
arr[0] = new int(1);
delete arr[0];
但我想说服他们放弃这个想法。让我们看看他们的最终目标:模板化 class
template <class TYPE>
class MyVector
{
std::unique_ptr<TYPE[]> arr; // array of whatever type
public:
MyVector(size_t size): arr(std::make_unique<TYPE[]> (size))
{
}
TYPE& operator[](size_t index)
{
return arr[index];
}
// note the complete lack of growing, shrinking and other vector goodness
// as they are not needed for this example.
};
我们可以将此 class 用于任何事情。
int main()
{
// vector of int
MyVector<int> vec(5);
vec[0] = 1;
// vector of pointer to int (yuck)
MyVector<int*> vec2(5);
vec2[0] = new int(1);
delete vec2[0];
// vector of smart pointer to int (also yuck, but less yuck)
MyVector<std::unique_ptr<int>> vec3(5);
vec3[0] = std::make_unique<int>(1);
// vector of std::string
MyVector<std::string> vec4(5);
vec4[0] = "I am the very model of a modern major general...";
}
如果向量的用户希望它包含指针,他们可以这样说。没有理由强制用户使用指针。
我假设下面的代码是 unique_ptr 数组(也不是我想要的)
std::unique_ptr<int[]> arr;
arr = std::make_unique<int[]> (5);
arr[0] = *new int(1);
delete &arr[0]; // malloc error, want to avoid "delete"
但是,我想要一个包含 unique_ptr 的数组,就像这样...
std::unique_ptr<int> arr2 []; //Error, requires explicit size
arr2 = std::make_unique<int> [5]; //Desirable, does not compile
arr2[0] = std::make_unique<int>(1); //Desirable, does not compile
如何制作 unique_ptr 数组?如果那不可能,那么我该如何处理 malloc 错误?
简短回答:使用向量。它们更容易使用,而且您不必显式分配内存。您还应该使用 typedef 来简化语法。
typedef unique_ptr<int> intPtr;
vector<intPtr> vec;
vec.push_back(make_unique<int>(69));
auto myIntPtr = make_unique<int>(16);
vec.push_back(move(myIntPtr)); // unique ptrs cannot be copied, must be moved
unique_ptr<int[5]> p1; // valid syntax
您想要一个包含 unique_ptr
的数组(如标题中所示),还是一个 unique_ptr
包含一个数组(如您的示例中所示)?
如果unique_ptr
的数组是你想要的,那么
std::vector<std::unique_ptr<int>>
或
std::array<std::unique_ptr<int>, 3>;
(例如)将完成这项工作。
如果 unique_ptr
持有一个数组是你想要的,那么 unique_ptr<int[]>
会起作用(有一个 partial specialisation of unique_ptr
to support it),虽然你不能使用 std::make_unique
并且需要自己给 operator new[]
打电话:
std::unique_ptr<int[]> p{new int[42]};
但是,如果您认为自己需要这个,那么您很可能真正想要的是 std::vector
,我强烈建议您改用它。
std::unique_ptr<int[]> arr;
arr = std::make_unique<int[]> (5);
此时你有一个unique_ptr
到int
的数组。这听起来正是您想要的。
arr[0] = *new int(1);
但这值得商榷。它动态分配单个 int
,将 1 分配给已分配的 int
,然后将已分配的 int
处的值 1 分配到元素 0 处的数组中。已分配的 int
被挂起,没有任何指向它,现在特别难以“删除”。这是内存泄漏。
delete &arr[0]; // malloc error, want to avoid "delete"
如您所见,这是致命的。不是尝试 delete
泄漏的 int
,而是使用指向存储在 unique_ptr
中的数组的指针调用 delete
。最终 unique_ptrwill try to
delete` 数组并失败,因为它已经消失了。
根据评论,OP 打算
std::unique_ptr<int*[]> arr;
arr = std::make_unique<int*[]> (5);
arr[0] = new int(1);
delete arr[0];
但我想说服他们放弃这个想法。让我们看看他们的最终目标:模板化 class
template <class TYPE>
class MyVector
{
std::unique_ptr<TYPE[]> arr; // array of whatever type
public:
MyVector(size_t size): arr(std::make_unique<TYPE[]> (size))
{
}
TYPE& operator[](size_t index)
{
return arr[index];
}
// note the complete lack of growing, shrinking and other vector goodness
// as they are not needed for this example.
};
我们可以将此 class 用于任何事情。
int main()
{
// vector of int
MyVector<int> vec(5);
vec[0] = 1;
// vector of pointer to int (yuck)
MyVector<int*> vec2(5);
vec2[0] = new int(1);
delete vec2[0];
// vector of smart pointer to int (also yuck, but less yuck)
MyVector<std::unique_ptr<int>> vec3(5);
vec3[0] = std::make_unique<int>(1);
// vector of std::string
MyVector<std::string> vec4(5);
vec4[0] = "I am the very model of a modern major general...";
}
如果向量的用户希望它包含指针,他们可以这样说。没有理由强制用户使用指针。