是否可以使用唯一指针实现std :: list?

时间:2018-12-02 16:36:22

标签: c++ list unique-ptr

List.h:

#pragma once
#include <iostream>
#include <memory>
#include <initializer_list>


class List{
    public:
        List();
        List(const std::initializer_list<int> &list);
        ~List();
        int size() const;

        void push_back(int val);
        void pop_back();
        void pop_front();
        friend std::ostream &operator << (std::ostream &os, const List &l);

    private:
        void printNodes() const;
        struct Node {
            Node(int data) : data(data) {}
            std::unique_ptr<Node> next;
            Node *previous;
            int data;
        };
        int len;
        std::unique_ptr<Node> head;
        Node *tail;
};

List.cpp

#include "List.h"

List::List() : len(0), head(nullptr), tail(nullptr){
}

List::List(const std::initializer_list<int> &list) : len(0), head(nullptr), tail(nullptr) {
    for (auto &elem : list)
        push_back(elem);
}

List::~List() {
}

void List::push_back(int val){
    if (tail == nullptr) {
        head = std::make_unique<Node>(val);
        tail = head.get();
        head->next = nullptr;
        head->previous = nullptr;
        len++;
    }
    else {
        tail->next = std::make_unique<Node>(val);
        (tail->next)->previous = tail;
        tail = tail->next.get();
        tail->next = nullptr;
        len++;
    }
}

void List::pop_back(){
    if(len == 1){
        auto node = head.release();
        delete node;
        head = nullptr;
        tail = nullptr;
    }else{
        // tail->previous;

    }
}

void List::pop_front(){
    if(len == 1){
        auto node = head.release();
        delete node;
        head = nullptr;
        tail = nullptr;
    }else{


    }
}

void List::printNodes() const{
    Node *temp = head.get();

    while (temp != nullptr) {
        std::cout << temp->data << "\n";
        temp = (temp->next).get();
    }
}

int List::size() const{
    return len;
}

std::ostream &operator<<(std::ostream & os, const List & l){
    l.printNodes();

    return os;
}

Source.cpp

#include <iostream>
#include "List.h"

using namespace std;

int main() {
    List l{3, 5, 1, 6, 7};

    cout << l << endl;
}

Hello Stack Overflow,我是一名数据结构专业的学生,​​作为练习,我正在尝试使用智能指针重新创建std::list。根据我的阅读,看来unique_ptr应该是默认使用的语言,shared_ptrweak_ptr仅在unique_ptr由于速度差异而不能使用的情况下使用。不幸的是,在尝试实现pop_back()pop_front()时遇到了麻烦。我是否必须采用共享指针来完成整个std :: list的重新实现,还是可以使用唯一指针来完成这些功能?

1 个答案:

答案 0 :(得分:0)

是的,这完全有可能。让我们从pop_back开始:

您已经有一个指向tail的节点的指针,但这并不是一个有趣的指针,因为它只是一个原始指针。您需要的指针是unique_ptr到同一节点。该指针存储在哪里?从tail开始有一种简单的方法吗?

一旦有了unique_ptr,就可以从列表中取消链接节点,就像resetting那个指针一样简单。请注意,无需手动调用releasedelete节点。

现在pop_front:在这里您已经拥有unique_ptr,它是head。但是您必须小心,因为整个列表都取决于此列表。重置head将使整个列表消失。因此,请确保从head分离列表的其余部分,然后首先将其与list重新连接。如果您正确执行此操作,则删除原始head甚至不会给您带来麻烦。试试吧!

请确保绘制列表的图片以可视化哪个节点指向何处。立即将所有这些信息保存在您的脑海中是很困难的。