【问题标题】:How to implement a copy constructor for a singly linked list utilizing smart pointers如何利用智能指针为单链表实现复制构造函数
【发布时间】:2016-10-16 02:56:39
【问题描述】:

这是我第一次在此处实际发布问题!我在为单链表创建复制构造函数时遇到了一些麻烦。我在这个网站和其他各种网站上搜索了一个可比较的例子,但无济于事。我试图使用智能指针,到目前为止只使用了unique_ptr(s)。此函数旨在对其传递的链表进行深层复制。到目前为止,我已经尝试了以下方法,但我只得到了一个段错误。我已经进行了一些测试,我相信我的 insert_front()insert_back() 函数运行良好。如果有帮助的话,我确实有指向头部和尾部的指针。以下是我试过的代码。

Deque::Deque(const Deque& deque2copy){
    this -> head = 0;
    unique_ptr<Node> temp = make_unique<Node>(deque2copy.head -> val, move(deque2copy.head->next));
    while(temp != 0){
        this ->insert_back(temp->val);
        temp = move(temp-> next);
    }
}

更新 #1

Deque::Deque(const Deque& deque2copy){

    if(deque2copy.head->next == nullptr){
        return;
    } else {
       this -> head = 0;
       unique_ptr<Node> temp = make_unique<Node>(*deque2copy.head->next);
       while(temp != 0){
            this ->insert_back(temp->val);
            temp = move(temp-> next);
       } 
    }

}

【问题讨论】:

  • 为什么要从被复制的容器中移出?那是auto_ptr 不直观
  • 没有move() 它似乎无法编译。我认为需要允许复制 unique_ptr ?
  • Move 可以从中移动。如果你搬家,你就不再得到原件了。我想你可能想要make_unique&lt;Node&gt;(*deque2copy.head-&gt;next)
  • 我现在只要调用复制构造函数就会出现段错误:/
  • 啊,那么只有当指针deque2copy.head-&gt;next不为空时才构造一个副本

标签: c++ linked-list copy-constructor smart-pointers deque


【解决方案1】:

您没有发布太多关于您的 DequeNode 类的实际外观的信息。根据从您的代码 sn-ps 中看到的信息,您的主要问题是您使用 std::unique_ptr&lt;T&gt; 导航您的列表:这不起作用:每当分配或销毁非空 std::unique_ptr&lt;T&gt; 时,它将释放持有的对象.你需要一个非拥有的指针。

由于您没有发布太多上下文信息,我无法轻松测试此代码是否有效,但我认为应该没问题:

Deque::Deque(const Deque& deque2copy)
    : head() { // the default constructor does the null-initialization
    std::unique_ptr<Node>* tail(&this->head);
    for (Node* temp(deque2copy.head.get()); temp; temp = temp->next.get()) {
        *tail = std::make_unique<Node>(temp->value);
        tail = &tail->next;
    }
}

请注意,此代码使用非拥有指针导航两个列表:

  • 对于源列表,它使用从std::unique_ptr&lt;Node&gt;::get() 获得的Node*,以避免在分配或销毁std::unique_ptr&lt;Node&gt; 时销毁Node 对象。
  • 对于目标列表,保留指向列表中当前最后一个std::unique_ptr&lt;Node&gt; 的指针tail(最初是head,一旦分配了这个指针,则列表中的最后一个next 指针)被保留以有效地附加节点。

代码确实假设Node 有一个构造函数,将value 作为构造函数参数。此构造函数将相应地初始化 value 成员并默认初始化 next 成员,例如:

Node::Node(T const& value)
    : value(value)
    , next() {
}

请注意,对列表的元素使用拥有指针通常是一个坏主意:head 的析构函数将递归调用列表中所有节点的析构函数。根据析构函数的实际编写方式,此递归可能很容易造成堆栈溢出。为了解决这个问题,您需要为您的列表编写一个自定义析构函数以避免这种递归。然而,这样做完全违背了使用std::unique_ptrs 来维护节点的初衷。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-20
    • 2016-10-13
    • 2015-02-28
    • 2017-09-13
    相关资源
    最近更新 更多