【问题标题】:How to make an array that holds unique_ptrs?如何制作一个包含 unique_ptrs 的数组?
【发布时间】:2017-07-28 18:50:31
【问题描述】:

我假设下面的代码是数组的 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_ptrs 的数组...

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_ptrs 数组?如果这不可能,那么我该如何处理 malloc 错误?

【问题讨论】:

  • 2 个简单的选项:std::array&lt;std::unique_ptr&lt;int&gt;, 5&gt;std::vector&lt;std::unique_ptr&lt;int&gt;&gt;
  • 您到底想完成什么?你真的需要unique_ptrs 的数组吗?
  • @NathanOliver,据说是的。这有什么奇怪的?
  • @SergeyA 你会这么想,但正如你从 OP 的评论中看到的那样,这不是他们所需要的。他们只需要std::unique_ptr&lt;Type[]&gt; 或新的缓冲区和位置。构建向量不需要unique_ptr 的数组。
  • @SergeyA 当然。不过,您必须平分奖金。

标签: c++ arrays c++14 unique-ptr


【解决方案1】:

简答:使用向量。它们更容易使用,您不必明确分配内存。您还应该使用 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_ptrs 数组(这与 unique_ptr 到数组不同)。
【解决方案2】:

您想要一个包含unique_ptrs 的数组(如标题所示),还是一个包含一个数组的unique_ptr(如您的示例所示)?


如果unique_ptrs 的数组是你想要的,那么

std::vector<std::unique_ptr<int>>

std::array<std::unique_ptr<int>, 3>;

(例如)将完成这项工作。


如果unique_ptr 持有一个数组是您所追求的,那么unique_ptr&lt;int[]&gt; 将起作用(有一个partial specialisation of unique_ptr to support it),尽管您不能使用std::make_unique 并且需要调用operator new[]你自己:

std::unique_ptr<int[]> p{new int[42]};

但是,如果您认为自己需要这个,那么您最可能真正想要的是 std::vector,我强烈建议您改用它。

【讨论】:

  • 是的,就像标题所暗示的那样,基本数组(而不是 std::array)呢?那可行吗?我也确实说过“但是,我想要一个包含 unique_ptrs 的数组”。提前感谢您的帮助。
【解决方案3】:
std::unique_ptr<int[]> arr;
arr = std::make_unique<int[]> (5);

此时您有一个unique_ptrint 的数组。这听起来正是您想要的。

arr[0] = *new int(1);

但这是值得怀疑的。它动态分配一个int,将1分配给分配的int,然后将分配的int处的值1分配到元素0处的数组中。分配的int被悬空,没有任何指向在它,现在异常难以`删除。这是内存泄漏。

delete &arr[0]; // malloc error, want to avoid "delete"

正如你所见,这是致命的。而不是试图delete 泄漏的intdelete 已被调用,并使用指向存储在unique_ptr 中的数组的指针。最终 unique_ptrwill try todelete 数组失败了,因为它已经消失了。

基于cmets,OP打算

std::unique_ptr<int*[]> arr;
arr = std::make_unique<int*[]> (5);
arr[0] = new int(1);
delete arr[0]; 

但我想说服他们放弃这个想法。让我们看看他们的最终目标:一个模板化的类

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.
};

我们几乎可以将这个类用于任何东西。

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...";
}

如果向量的用户希望它包含指针,他们可以这样说。没有理由强迫用户使用指针。

【讨论】:

    猜你喜欢
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    • 2020-02-03
    • 2015-12-22
    • 1970-01-01
    • 2020-05-24
    • 1970-01-01
    • 2015-12-24
    相关资源
    最近更新 更多