【问题标题】:How to use std::shared_ptr as class member?如何使用 std::shared_ptr 作为类成员?
【发布时间】:2016-12-03 10:03:45
【问题描述】:

我需要创建一个这样的类。但是当我运行这段代码时,我得到:

"Error in `./a.out': free(): invalid next size (fast)"

MyClass 有什么问题?如何正确使用 shared_ptr 作为类成员?

#include <memory>

class MyClass
{
public:
    MyClass(unsigned size) {
        _size = size;
        _arr = std::make_shared<int>(size);
        for (int i = 0; i < size; i++)
            _arr.get()[i] = 0;
    }

    MyClass(const MyClass& other) {
        _arr = other._arr;
        _size = other._size;
    }

    MyClass& operator=(const MyClass& other) {
        _arr = other._arr;
        _size = other._size;
    }

    void setArr(std::shared_ptr<int> arr, unsigned size) {
        _size = size;
        _arr = arr;
    }

    ~MyClass() {
        _arr.reset();
    }

private:
    std::shared_ptr<int> _arr;
    unsigned _size;
};

int main() {
    MyClass m(4);
    return 0;
}

谢谢,我误解了 make_shared 的作用。如果我想使用 int*(不是 std::vector 或 std::array),我应该写这个吗? (并且不要修复其他方法)

    MyClass(unsigned size) {
        _size = size;
        _arr = std::shared_ptr<int>(new int[size]);
        for (int i = 0; i < size; i++)
            _arr.get()[i] = 0;
    }

【问题讨论】:

  • 提示:指针不是数组。仔细想想这意味着什么:std::make_shared&lt;int&gt;(size);.
  • 另请注意,您的问题与智能指针作为数据成员无关。
  • 您说您“需要创建这样的类”并且您不“想使用”简单的标准解决方案 (std::vector)。为什么?你绝对必须使用std::shared_ptr的原因是什么?
  • @AnatoliySultanov:你考虑过std::shared_ptr&lt;std::vector&lt;int&gt;&gt;吗?
  • @AnatoliySultanov:是的,你是否需要一个“动态数组”(即真实代码中的std::vector,除非你有一个非常需要手动的特殊用例如果仅在运行时知道大小,则使用placement new)。只有在程序运行之前知道大小时,才能使用std::array。永远不要使用new[]

标签: c++ c++11 memory-management smart-pointers


【解决方案1】:

请看看std::make_shared 是如何工作的。

基本上,std::make_shared

构造一个类型为 T 的对象并将其包装在 std::shared_ptr 中

在你的情况下 Tint,所以 std::make_shared 创建了一个 int 类型的对象并且将其包装在 std::shared_ptr 中。因此,内存是为单个 int 分配的,而不是为 int 数组分配的,并且您的程序会导致 Undefined Behaviour

我想你可以使用std::default_delete 来避免问题:

_arr = std::shared_ptr<int>(new int[size], std::default_delete<int[]>());

还要注意:

  1. 您的 operator= 没有返回任何内容。
  2. 变量名称不应以下划线开头。
  3. 没有必要在类析构函数中为 _arr 调用 reset()

【讨论】:

  • std::vector 不会有相同的所有权语义。这实际上可能是一件好事,但不是 OP 的目标。
  • 你应该通过值传递 std::shared_ptr 因为它是一个指针抽象。还可以将 std::shared_ptr 与适当的删除器一起使用。
  • @AnatoliySultanov setArr 方法已损坏,因为您可以传递与“大小”或 shared_prt 数组不匹配的大小。只需删除它,以及赋值运算符、复制构造函数和析构函数,并使用编译器为您制作的那些。
  • @AnatoliySultanov:如果事先知道数字 10,那么您可以使用 std::shared_ptr&lt;std::array&lt;int, N&gt;&gt; 并将 MyClass 设为模板。请注意,您的真正问题已经与您的原始问题(如何使用std::shared_ptr 作为班级成员)有很多的偏差。
  • @AnatoliySultanov 所有你需要它y = x;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-08
  • 2011-04-02
  • 1970-01-01
  • 1970-01-01
  • 2014-08-06
  • 1970-01-01
相关资源
最近更新 更多