std::unique_ptr<> 作为基于节点的结构中的指针

std::unique_ptr<> as pointer in a node based structure

本文关键字:节点 于节点 指针 结构 ptr unique lt gt std      更新时间:2023-10-16

由于大多数人喜欢的谜题I,将以一个(拼写错误:)gotw式的介绍开始这个问题,请注意如果你不在乎,你可以跳过热身(JG问题),阅读G问题,因为这是我的"真正的SO问题"。

在审查潜在新员工提供的代码样本期间您偶然发现了一个链表,它的实现使用了现代C++11功能,std::unique_ptr<>。

template <typename T> 
struct Node { 
   T data; 
   std::unique_ptr<Node<T>> next; 
   Node () {} 
   Node(const T& data_): data(data_) {} 
   Node(Node& other) { std::static_assert(false,"OH NOES"); } 
   Node& operator= (const Node& other) { 
     std::static_assert(false,"OH NOES"); 
     return *new Node(); 
   } 
public: 
   void addNext(const T& t) { 
      next.reset(new Node<T>(t)); 
   }
};
template<typename T>
class FwdList
{
    std::unique_ptr<Node<T>> head;
public:
    void add(const T& t)
    {
        if (head == nullptr)
            head.reset( new Node<T>(t));
        else {
            Node<T>* curr_node = head.get();
            while (curr_node->next!=nullptr) {
                curr_node = curr_node->next.get();
            }
            curr_node->addNext(t);
        }
    }
    void clear() {
        head.reset(); 
    }
 };

JG问题:

确定(忽略缺失的功能)此问题密码

G问题:(增加了2。基于答案)
1.

是否有办法解决在JG部分中检测到的问题不使用原始指针的问题?

2.

修复是否适用于节点包含多个指针的容器(例如,二进制树具有指向左、右子级的指针)

答案:
JG:

stackoverflow:)。原因:unique_ptr<>的递归析构器由.clear()函数触发。

G:

(??)我不知道,我的直觉是否定的,但我想和专家们。

长话短说:有没有一种方法可以在基于节点的结构中使用智能指针,而不会出现So问题?请不要说树可能不会太深,或者类似的事情,我正在寻找一般的解决方案。

您可以反复清除它,确保每个节点的next指针在销毁节点之前为空:

while (head) {
    head = std::move(head->next);
}

二叉树比较棘手;但是,您可以通过反复剪切右侧分支并将其添加到左下角,将其扁平化为列表,类似于以下内容:

node * find_bottom_left(node * head) {
    while (head && head->left) {
        head = head->left.get();
    }
    return head;
}
node * bottom = find_bottom_left(head.get());
while (head) {
    bottom->left = std::move(head->right);
    bottom = find_bottom_left(bottom);
    head = std::move(head->left);
}