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 指向真正的队尾。

     
  • 相关阅读:
    ORA-12520: TNS:监听程序无法为请求的服务器类型找到可用的处理程序解
    Django2.1.2创建默认管理后台
    堡垒机实例以及数据库操作
    pycharm常用快捷键
    Linux命令之sftp
    oracle收集ash和awr性能报告方法
    linux-php5.6-安装sftp扩展
    linux系统安全设置策略
    Openssh版本升级修复漏洞
    Android Studio下HierarchyViewer的使用
  • 原文地址:https://www.cnblogs.com/wuOverflow/p/4832256.html
Copyright © 2011-2022 走看看