共享指针交换方法标识更改
shared pointer swap method identity change
背景:
我不知道是什么原因导致我对此进行试验,但我正在尝试测试内部使用智能指针的容器化 linked 列表。
这是回复link:
https://repl.it/@BasavarajNagar/GoodnaturedGlisteningSection-1
#include <memory>
using namespace std;
template<typename T>
class linkedlist {
private:
class node {
public:
T data;
shared_ptr<node> next;
node(T data) {
this->data = data;
}
};
// non const unique ptr
shared_ptr<node> head;
public:
void add(T data) {
cout<< "adding " << endl;// + data << endl;
if (head == nullptr) {
head = shared_ptr<node>(new node(data));
return;
}
shared_ptr<node> cursor;
cursor.swap(head);
// this works well
while (cursor != nullptr) {
cout << cursor->data << endl;
cursor = cursor->next;
}
cout << data << endl;
// this is the problematic assignment
cursor = shared_ptr<node>(new node(data));
}
void trace() {
shared_ptr<node> cursor;
cursor.swap(head);
cout << "trace" << endl;
while (cursor != nullptr) {
cout << cursor->data << endl;
cursor = cursor->next;
}
}
};
int main() {
std::cout << "Hello World!\n";
linkedlist<int> ll;
ll.add(22);
ll.add(45);
ll.add(63);
ll.trace();
}
trace 方法总是指向最后一个元素,在 add 方法中交换后头部丢失。
注意:
我知道这不是生产质量代码,而是了解 internals/quirks 的智能指针。所以,请避免代码质量注释。
你严重误解了共享指针。 https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr
您最需要的跟踪信息是 node::node 和 node::~node。跟踪实际节点何时创建和销毁将对您有所帮助。您还必须了解范围。
对你的 "add" 函数的快速评论(留给你的修复,超出了问题的范围,对我来说 post 太多了):
它正确地创建了单个项目列表。但是,如果您尝试再次添加,您会将 head 移动到一个临时对象,将 head 设置为 nullptr。然后,您在列表中循环游标,破坏可能存在的任何节点,直到不再存在为止。您刚刚将 nullptr 分配给 cursor 这一事实不是问题,因为您会立即抛出它可能具有的任何值,然后创建一个包含单个项目的新列表,由 cursor 而不是 head 持有。然后您超出范围,破坏游标,因此也破坏了您刚刚添加到游标的新项目。
但最大的问题是你的跟踪功能,你用它来了解你的列表,但它并没有像你想要的那样远程做任何事情。这是最大的问题,因为你认为你基于错误的信息了解正在发生的事情。如果 trace 骗了你,那么你就无法使用它来理解 add。
这是一个跟踪函数,可以正确打印列表的当前内容,而不会破坏它:
void trace() {
cout << "trace: ";
shared_ptr<node> cursor = head; // SHARE, do not lose head, read the docs
while (cursor.get()) {
cout << cursor->data << ", ";
cursor = cursor->next;
}
cout << endl;
}
我建议连续调用两次跟踪函数。如果它在打印列表时没有破坏它,那么第二次调用应该与第一次调用具有相同的输出。要修复添加,您需要对其进行简化。只需按照您应该在常规节点指针上执行的操作即可。你的大问题是使用 "swap" 将你的实际数据置于一个临时对象的唯一控制之下,这将很快完成它的工作,这会破坏你的所有数据。
背景: 我不知道是什么原因导致我对此进行试验,但我正在尝试测试内部使用智能指针的容器化 linked 列表。
这是回复link: https://repl.it/@BasavarajNagar/GoodnaturedGlisteningSection-1
#include <memory>
using namespace std;
template<typename T>
class linkedlist {
private:
class node {
public:
T data;
shared_ptr<node> next;
node(T data) {
this->data = data;
}
};
// non const unique ptr
shared_ptr<node> head;
public:
void add(T data) {
cout<< "adding " << endl;// + data << endl;
if (head == nullptr) {
head = shared_ptr<node>(new node(data));
return;
}
shared_ptr<node> cursor;
cursor.swap(head);
// this works well
while (cursor != nullptr) {
cout << cursor->data << endl;
cursor = cursor->next;
}
cout << data << endl;
// this is the problematic assignment
cursor = shared_ptr<node>(new node(data));
}
void trace() {
shared_ptr<node> cursor;
cursor.swap(head);
cout << "trace" << endl;
while (cursor != nullptr) {
cout << cursor->data << endl;
cursor = cursor->next;
}
}
};
int main() {
std::cout << "Hello World!\n";
linkedlist<int> ll;
ll.add(22);
ll.add(45);
ll.add(63);
ll.trace();
}
trace 方法总是指向最后一个元素,在 add 方法中交换后头部丢失。
注意: 我知道这不是生产质量代码,而是了解 internals/quirks 的智能指针。所以,请避免代码质量注释。
你严重误解了共享指针。 https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr
您最需要的跟踪信息是 node::node 和 node::~node。跟踪实际节点何时创建和销毁将对您有所帮助。您还必须了解范围。
对你的 "add" 函数的快速评论(留给你的修复,超出了问题的范围,对我来说 post 太多了):
它正确地创建了单个项目列表。但是,如果您尝试再次添加,您会将 head 移动到一个临时对象,将 head 设置为 nullptr。然后,您在列表中循环游标,破坏可能存在的任何节点,直到不再存在为止。您刚刚将 nullptr 分配给 cursor 这一事实不是问题,因为您会立即抛出它可能具有的任何值,然后创建一个包含单个项目的新列表,由 cursor 而不是 head 持有。然后您超出范围,破坏游标,因此也破坏了您刚刚添加到游标的新项目。
但最大的问题是你的跟踪功能,你用它来了解你的列表,但它并没有像你想要的那样远程做任何事情。这是最大的问题,因为你认为你基于错误的信息了解正在发生的事情。如果 trace 骗了你,那么你就无法使用它来理解 add。
这是一个跟踪函数,可以正确打印列表的当前内容,而不会破坏它:
void trace() {
cout << "trace: ";
shared_ptr<node> cursor = head; // SHARE, do not lose head, read the docs
while (cursor.get()) {
cout << cursor->data << ", ";
cursor = cursor->next;
}
cout << endl;
}
我建议连续调用两次跟踪函数。如果它在打印列表时没有破坏它,那么第二次调用应该与第一次调用具有相同的输出。要修复添加,您需要对其进行简化。只需按照您应该在常规节点指针上执行的操作即可。你的大问题是使用 "swap" 将你的实际数据置于一个临时对象的唯一控制之下,这将很快完成它的工作,这会破坏你的所有数据。