unique_ptr:链表项删除

TeX*_*TeX 7 c++ linked-list undefined-behavior unique-ptr

我目前正在考虑在unique_ptrs的帮助下实现单个链表.尽管由于析构函数的递归调用可能导致堆栈溢出的问题(请参阅Stack overflow with unique_ptr链表),但我遇到了以下问题:假设,我们有以下链表实现

struct node {
  node (void) : val(0), next(nullptr) {}
  int val;
  std::unique_ptr<node> next;
};
Run Code Online (Sandbox Code Playgroud)

我们已经按照初步确定了我们的清单

int main (int argc, char* argv[]) {
  node HEAD;
  HEAD.val = 0;
  auto ptr = &HEAD;
  for (int i = 0; i < 10; ++i) {
    ptr->val = i;
    ptr->next.reset(new node);
    ptr = ptr->next.get();
  }
  ptr->val = 10;
  ...
Run Code Online (Sandbox Code Playgroud)

现在,我想删除值为1的节点:

ptr = &HEAD;
ptr = ptr->next.get();
HEAD.next = std::move(ptr->next);
Run Code Online (Sandbox Code Playgroud)

乍一看,这似乎是明智的.不过,我不确定它是否会导致未定义的行为:

根据http://en.cppreference.com/w/cpp/memory/unique_ptr/operator%3D,运营商=

将所有权从r转移到*这就好像通过调用reset(r.release())然后从std :: forward(r.get_deleter())分配get_deleter()一样

仔细看看unique_ptr :: reset(http://en.cppreference.com/w/cpp/memory/unique_ptr/reset),它会读到

给定current_ptr,由*this管理的指针按
以下顺序执行以下操作:

  1. 保存当前指针old_ptr = current_ptr的副本

  2. 使用参数current_ptr = ptr覆盖当前指针

  3. 如果旧指针非空,则删除以前管理的对象if(old_ptr!= nullptr)get_deleter()(old_ptr)

这意味着在这种情况下,r.get_deleter()的调用将引用一个已经被销毁的对象,或者我在这里弄错了?

非常感谢您的回复.

Jos*_*and 3

你的担忧对我来说似乎是有道理的。ptr->next.get_deleter() 不再存在,因为随着重置而ptr->next被销毁(尽管不再拥有任何东西) 。在大多数情况下,这可能并不重要,因为删除器将是一个空基类,并且赋值将是一个无操作,但技术上仍然是未定义的行为。*ptrptr

我会HEAD.next.reset(ptr->next.release());明确同意(如果您不关心删除程序),或者HEAD.next = std::unique_ptr<node>(std::move(ptr->next))如果您担心保留删除程序。