C ++设置指针等于shared_ptr

时间:2016-07-14 02:56:17

标签: c++ c++11

我正在尝试使用链接列表的概念创建一个List类,虽然我最初使用的是C ++标准new关键字,但我决定将其切换为C ++ 11 {{1 }}。但是,当使用智能指针时,我无法使程序正常运行,因为它崩溃了。以下是更改前的一些代码:

std::shared_ptr

这就是变化的样子:

class List
{
public:
    void push_back(...) {
        Node *temp = new Node;
        ...
        if (!head) {
            head = temp;
            return;
        }
        else {
            Node *last = head;
            ...
            last->next = temp;
        }
    }
    ...

private:
    Node *head = nullptr;
};

我觉得问题可能是class List { public: void push_back(...) { std::shared_ptr<Node> temp(new Node); ... if (!head) { head = temp.get(); return; } else { Node *last = head; ... last->next = temp.get(); } } ... private: Node *head = nullptr; // don't need this to be a smart ptr }; head没有动态分配,也许他们需要使用last,但我不确定。我究竟做错了什么,我该如何解决?我真的希望这不是重复,因为我似乎无法找到解决我问题的任何东西。感谢。

编辑: 这是shared_ptr结构:

Node

2 个答案:

答案 0 :(得分:4)

首先拥有std::shared_ptr的原因是让std::shared_ptr获得指针的完整和完全所有权,并使std::shared_ptr对{delete负责1}},一旦指针的最后一个引用消失了。这就是std::shared_ptr的全部内容。

这意味着一旦将指针放入std::shared_ptrstd::shared_ptr现在就完全负责管理指针。它完全拥有它。

因此,将指针放入std::shared_ptr ......然后立即取出它是没有意义的:

head = temp.get();

get()功能存在原因,但这不是其中之一。

为了正确使用std::shared_ptr,所有内容都必须为std::shared_ptrhead必须是std::shared_ptr

std::shared_ptr<Node> head; // yes, it does need to be a smart ptr

为什么需要std::shared_ptr?好吧,如果不是,你认为这会发生什么:

std::shared_ptr<Node> temp(new Node);

具体来说,当这个temp智能指针被销毁时,此函数何时返回?好吧,因为它将是引用此std::shared_ptr的最后一个Node,所以很高兴delete它。您事先get()并将其置于head这一事实并不重要。现在,您有head指向delete d节点。随之欢闹。

这就是为什么一切都必须是std::shared_ptr。不仅head,而且Node next成员 也需要成为std::shared_ptr也是。

现在,有一个涉及循环引用的陷阱,当std::shared_ptr进入图片时会发挥作用。但这将成为一个不同的问题。

答案 1 :(得分:1)

您的主要问题是,如果您要使用shared_ptr,最好一直使用它。将next设为shared_ptr而不是原始。{/ p>

struct Node {
    int data;
    std::shared_ptr<Node> next;
}

引擎盖下的std::shared_ptr所做的是保持对指针的引用数量的计数。当您使用复制构造函数或operator= 时,它会增加引用计数。当一个实例超出范围导致析构函数被调用(或者你给它一个带有operator=的不同指针)时,引用计数会减少。当计数为零时,指针被销毁。

// pass by value invokes copy constructor (refcount + 1)
void myFunc(std::shared_ptr<MyClass> var) {

    // Code using var

} // end of function invokes destructor (refcount - 1)

void run() {
    std::shared_ptr<MyClass> ptr(new MyClass); // refcount = 1
    myFunc(ptr); // refcount = 2
    // After myFunc returns refcount = 1

}
int main() {
    run(); // refcount = 1
    // After run returns, refcount = 0 and the pointer is deleted
}

通过使用get(),您可以引入一个指向内存的指针,该指针可能会在某个时刻被删除,无论该指针是否在周围。这可能导致段错误,因为原始指针指向shared_ptr删除的内存。

这是因为get()不会影响引用计数。怎么可能呢?它不再是shared_ptr,因此类定义无法知道您使用它做什么,或者何时被删除。如果get()增加了引用计数,那么之后就没有什么可以减少它,并且永远不会释放内存。这是内存泄漏!