Hap*_*ing 7 c++ stack-overflow linked-list unique-ptr c++11
我已经转换了以下链表结构
struct node {
node* next;
int v;
};
Run Code Online (Sandbox Code Playgroud)
进入c ++ 11版本 - 没有使用指针.
struct node {
unique_ptr<node> next;
int v;
};
Run Code Online (Sandbox Code Playgroud)
添加,删除元素和遍历工作正常,但是当我插入大约1mil元素时,当调用头节点的析构函数时,我得到堆栈溢出.
我不确定我做错了什么.
{
node n;
... add 10mill elements
} <-- crash here
Run Code Online (Sandbox Code Playgroud)
正如在其他答案中所解释的那样,由于递归隐式析构函数,您会出现段错误.可以在不使用原始指针的情况下解决这个问题,不得不信任编译器或编写自定义分配器:
~node() {
for (std::unique_ptr<node> current = std::move(next);
current;
current = std::move(current->next));
}
Run Code Online (Sandbox Code Playgroud)
在这里,您迭代地浏览指针链.这将一个一个地取消一个指针并将所有权更改std::move(current->next)为当前.同时,current由移动分配覆盖的前一个未链接指针将被释放.
您可能会发现显式变体更直接:
current.reset(current->next.release()));
Run Code Online (Sandbox Code Playgroud)
实际上是有效的:
current = std::move(current->next));
Run Code Online (Sandbox Code Playgroud)
我更喜欢这个move版本,因为它在任何时候都没有给你一个原始指针.但在这种情况下,它并没有什么不同.
你这里没有错.
当您创建包含1000万个元素的列表时,为每个节点分配make_unique一切都很好(当然,数据不在堆栈中,除了第一个节点!).
问题是,当你摆脱列表的头部时: unique_ptr将负责删除它拥有的下一个节点,其中还包含一个unique_ptr将负责删除下一个节点......等等...
因此,最终以递归方式删除了10百万个元素,每个递归调用占用了堆栈上的一些空间.
默认情况下,std::unique_ptr调用std::default_delete刚执行运算符的结构的运算符函数delete.
因此结构的每个运算符函数std::default_delete递归地next为结构的数据成员调用自身node.
结果你得到堆栈溢出.
如果您使用普通指针而不是类型的指针std::unique_ptr但是通过以下方式向结构节点添加了析构函数,您将得到相同的结果
struct node {
node* next;
int v;
~node() { delete next; }
};
Run Code Online (Sandbox Code Playgroud)
甚至喜欢
struct node {
node* next;
int v;
~node() { if ( next ) delete next; }
};
Run Code Online (Sandbox Code Playgroud)
对于具有大量节点的列表,因为将以递归方式调用析构函数
| 归档时间: |
|
| 查看次数: |
3215 次 |
| 最近记录: |