zoukankan      html  css  js  c++  java
  • 极简单的单线程队列

    template<typename T>
    class Queue
    {
    private:
        struct Node
        {
            T                  data;
            std::unique_ptr<T> next = nullptr;
            Node(T _data):
                data(std::move(_data))
            {}
        };
    
        std::unique_ptr<Node> head = nullptr;
        Node*                 tail = nullptr;
    public:
        Queue()                        = default;
        Queue(const Queue&)            = delete;
        Queue& operator=(const Queue&) = delete;
    
        std::shared_ptr<T> tryPop()
        {
            if (head == nullptr){
                return std::shared_ptr<T>();
            }
    
            auto const result  = std::make_shared<T>(std::move(head->data));
            auto const oldHead = std::move(head);
            head = std::move(oldHead->next);
            return result;
        }
    
        void push(T newVal)
        {
            auto newNextNode = std::make_unique<Node>(std::move(newVal));
            auto newTail = newNextNode.get ();
            if (tail != nullptr){
                tail->next = std::move(newNextNode);
            }
            else{
                head = std::move(newNextNode);
            }
            tail = newTail;
        }
    
    };

    我也曾怀疑,为何不把 tail 也作为一个 unique_ptr,所以使用了一个反证法。若 tail 的类型是一个 unique_ptr,那么当 push 一个新值的时候,接下来的操作应该是:

    auto newTail = make_unique<T>(newValue);
    tail->next = move(newTail);
    tail = move(newTail); // oops!

    问题就出在第三行。怎么说呢,如果是拷贝语义,那么是没错的,然而使用的是 move,这样在使用了第一个 move 操作之后,newTail 就会被析构,第二个 move 移动的是一个 nullptr。

    当然,如果全部使用裸指针倒是可以这样:

    auto newTail = new Node(newValue); // 新结点
    tail->next = newTail;              // 新节点成为现 tail 的 next    
    tail = newTail;                    // 让 tail 指向真正的新节点

    倒是达到了效果,但是对于其资源的释放又成了一个棘手的问题,因此把 head 和 tail 的类型分别设为 unique_ptr 和  Node* 就有意义了。添加元素时,为了新节点的信息得以保存,先根据添加的值构造一个 unique_ptr 来代替原先 tail 的 next,又因为在使用 move 移动这个 unique_ptr 之后,其本身会被析构,所以在代替之前,需要先使用 get 得到新链表节点的信息然后再在最后让 tail 指向真正的队尾。

     
  • 相关阅读:
    [LeetCode] Happy Number 快乐数
    imread() not working in OpenCV 2.4.11 Debug mode
    OpenCV 3.0 VS2010 Configuration
    [LeetCode] 22. Generate Parentheses 生成括号
    [LeetCode] 24. Swap Nodes in Pairs 成对交换节点
    [LeetCode] 25. Reverse Nodes in k-Group 每k个一组翻转链表
    [LeetCode] 29. Divide Two Integers 两数相除
    [LeetCode] Bitwise AND of Numbers Range 数字范围位相与
    [LeetCode] 31. Next Permutation 下一个排列
    [LeetCode] 32. Longest Valid Parentheses 最长有效括号
  • 原文地址:https://www.cnblogs.com/wuOverflow/p/4832256.html
Copyright © 2011-2022 走看看