我有一些具有大量链接的链表(它们最多可包含20,000个项目)。它们有不同的开端,但它们最终可以从某个节点开始指向相同的节点。我决定让这样的链接列表共同增长并共享它们之间的内存。
这就是为什么我决定使用共享指针实现链接列表的原因:
#include <memory>
struct SharedLinkedList {
int someData;
std::shared_ptr<SharedLinkedList> next;
};
这样一切都正常工作。不再需要的链表将被删除。如果它们与其他链表共享某些部分,则仅删除它们未共享的部分。
当要删除没有共享部分的较长链表时,问题出现了。删除从第一个元素开始。这会减少对下一个元素的引用数量,下一个元素也可以被递归地删除,直到堆栈溢出。
下面是创建长链表并尝试删除它时失败的代码示例:
SharedLinkedList* beginningOfList;
SharedLinkedList* actualElement = new SharedLinkedList();
SharedLinkedList* nextElement;
beginningOfList = actualElement;
for (int i = 0; i < 1000; i++) { // 100 is OK, 1000 is KO
nextElement = new SharedLinkedList();
actualElement->next = std::shared_ptr<SharedLinkedList>(nextElement);
actualElement = nextElement;
}
delete beginningOfList;
我提前感谢你能回答以下问题中的任何一个:
1. shared_pointers的解释以及我可能遗漏的内容。我该如何使用它们?并且是否可以使用它们实现所需功能?难道共享内存不是为了发明共享指针而产生的吗? 2. 如何重新实现我的代码? 3. 这段代码将用于在我的计算机上运行的科学计算。我能否通过某种方式调整一些设置,以便拥有更大的堆栈大小?
请注意,此问题与C ++11无关。我不在乎使用哪种shared pointers的实现方式。我甚至已经实现了自己的共享指针。这允许我拥有稍长的链接列表,但析构函数中的递归和堆栈溢出也出现了。我不知道共享指针如何在没有析构函数递归的情况下实现。
编辑:
只是为了避免混淆:我想重申,整个列表可以共享。因此,可以称它们为树。
以下是示例: list1包含:1,2,3,4,5,6,7。 list2包含:6,6,6,1,2,3,4,5,6,7。 list3包含:10,11,12,1,2,3,4,5,6,7。
我想在3个SharedLinkedList中表示它们,这样就不会浪费存储1,2,3,4,5,6,7多次的内存,而是它们指向同一个位置。这就是为什么需要引用计数。
delete list3; 应该只删除未共享的部分,即元素10,11,12。
SharedLinkedList
析构函数的实现。它显然调用了第一个项的析构函数,然后递归地调用下一个项的析构函数,以此类推。您应该很容易地改变SharedLinkedList
析构函数的实现方式,使其不使用递归函数调用(例如,使用while循环遍历列表中的元素)。 - jogojapanstd::list
(或std::vector
)和std::shared_ptr
? - Some programmer dudeSharedLinkList
使用了编译器生成的析构函数。你不能真正添加一个迭代所有剩余列表的析构函数;整个重点是节点被引用计数。 - jamesdlin