【问题标题】:std::unique_ptr constructor behaviourstd::unique_ptr 构造函数行为
【发布时间】:2020-01-20 15:28:55
【问题描述】:

首先,我知道我们应该使用std::make_unique() 而不是调用std::unique_ptr 构造函数,我知道为什么。

但我正在查看std::unique_ptr 的文档以打发时间并加深对它的了解,我发现following examples 关于构造函数的用法:

// unique_ptr constructor example
#include <iostream>
#include <memory>

int main () {
  std::default_delete<int> d;
  std::unique_ptr<int> u1;
  std::unique_ptr<int> u2 (nullptr);
  std::unique_ptr<int> u3 (new int);
  std::unique_ptr<int> u4 (new int, d);
  std::unique_ptr<int> u5 (new int, std::default_delete<int>());
  std::unique_ptr<int> u6 (std::move(u5));
  std::unique_ptr<int> u7 (std::move(u6));
  std::unique_ptr<int> u8 (std::auto_ptr<int>(new int));

  std::cout << "u1: " << (u1?"not null":"null") << '\n';
  std::cout << "u2: " << (u2?"not null":"null") << '\n';
  std::cout << "u3: " << (u3?"not null":"null") << '\n';
  std::cout << "u4: " << (u4?"not null":"null") << '\n';
  std::cout << "u5: " << (u5?"not null":"null") << '\n';
  std::cout << "u6: " << (u6?"not null":"null") << '\n';
  std::cout << "u7: " << (u7?"not null":"null") << '\n';
  std::cout << "u8: " << (u8?"not null":"null") << '\n';

  return 0;
}

它生成(我通过执行代码验证了它)以下结果:

u1: 空
u2: 空
u3:不为空
u4:不为空
u5: 空
u6: 空
u7:不为空
u8: 不为空

我很难理解的是:

  • 为什么u4 有效而u5 无效(nullptr)?
  • 为什么u7 有效但u6 无效?

也许这些问题非常基本,但我完全没有抓住重点。

如果有人能就这些问题启发我,我将不胜感激。

【问题讨论】:

  • u5 在初始化 u6 时死亡,then u6 在初始化 u7 时死亡。 std::unique_ptr 将在移动时变为 null,根据设计,强制保证其唯一所有权。
  • @AlanBirtles TLDR:创建多个 unique_ptr 变量作为函数参数并且其中一个抛出时的异常安全性。参见例如stackoverflow.com/a/22571331/256138

标签: c++ smart-pointers move-semantics


【解决方案1】:

std::move 被命名为 move 是有原因的。当你从一个std::unique_ptr 移动到另一个时,你移动的那个变成了nullptr。不可能有任何其他方式,毕竟它是一个唯一 ptr,共享相同数据的两个unique_ptr 实例会违反这一点。 (而且两者都超出范围会调用删除器两次,然后一切都变得松散了。)

【讨论】:

    【解决方案2】:

    为什么 u4 有效而 u5 无效(nullptr)?

    因为u5u6 的初始化中被移出,而u4 尚未被移出。移动构造函数保证将移动的指针设置为空。它不能指向与u6 相同的对象,因为这会违反唯一性约束。

    为什么 u7 有效但 u6 无效?

    同样的原因。

    【讨论】:

    • 哦,对了,我太笨了……累了。谢谢你的解释。
    【解决方案3】:

    移动一个唯一拥有的对象意味着新所有者拥有它,而之前的所有者一无所有。
    就像物理对象在现实世界中的工作方式一样。

    所有者转换为空指针表示什么都没有。

    最初由u5 拥有的对象已先移至u6,然后移至u7

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-04
      • 1970-01-01
      相关资源
      最近更新 更多