c++ - 为什么 observer_ptr 在 move 后不归零?

标签 c++ pointers c++11 move

为什么不是 observer_ptr move 操作后归零?

它在默认构造中被正确设置为 nullptr,这确实有意义(并防止指向垃圾)。

相应地,当 std::move() 开始时,它应该被清零,就像 std::stringstd::vector

这将使它成为多个上下文中的一个很好的候选者,在这些上下文中,原始指针是有意义的,并且自动在具有原始指针数据成员的类上生成 move 操作,例如 this case .


编辑

正如@JonathanWakely 在评论中指出的(与 aforementioned question 相关):

if observer_ptr was null after a move it can be used to implement the Rule of Zero for types that have a pointer member. It's a very useful feature.

最佳答案

一开始似乎很多人都忽略了这个想法的要点和实用性。

考虑:

template<typename Mutex>
class unique_lock
{
  Mutex* pm;

public:
  unique_lock() : pm() { }

  unique_lock(Mutex& m) : pm(&m) { }

  ~unique_lock() { if (pm) pm->unlock(); }

  unique_lock(unique_lock&& ul) : pm(ul.pm) { ul.pm = nullptr; }

  unique_lock& operator=(unique_lock&& ul)
  {
    unique_lock(std::move(ul)).swap(*this);
    return *this;
  }

  void swap(unique_lock& ul) { std::swap(pm, ul.pm); }
};

使用默认构造时为空且 move 后为空的“哑”智能指针,您可以默认三个特殊成员函数,因此它变为:

template<typename Mutex>
class unique_lock
{
  tidy_ptr<Mutex> pm;

public:
  unique_lock() = default;                            // 1

  unique_lock(Mutex& m) : pm(&m) { }

  ~unique_lock() { if (pm) pm->unlock(); }

  unique_lock(unique_lock&& ul) = default;            // 2

  unique_lock& operator=(unique_lock&& ul) = default; // 3

  void swap(unique_lock& ul) { std::swap(pm, ul.pm); }
};

这就是为什么有一个愚蠢的、非拥有的、 move 后为空的智能指针很有用,比如tidy_ptr

但是 observer_ptr 只是默认构造时为 null,所以如果它被标准化,它对于声明一个采用非拥有指针的函数很有用,但它不会有用对于像上面这样的类,所以我仍然需要另一个 非拥有哑指针类型。拥有两个非拥有的哑智能指针类型似乎比没有的更糟糕!

关于c++ - 为什么 observer_ptr 在 move 后不归零?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22310878/

相关文章:

c++ - 在 vector<Point> 中存储非零元素的坐标时 findnonzero() 出错

c - 什么是文件位置指针?

c++ - C++中的非空终止字符数组

c++ - 模板的构造函数和析构函数的名称

c++ - 为什么 const 函数返回左值而不是右值?

c++ - nullptr 可以用作变量参数(varargs)吗?

c++ - 将派生对象存储到 void*,然后从中转换基对象是否不安全?

Typedef 中的 C++ 指针

永不退出的 C++ boost::thread

c++ - 在 vector 中使用现有对象,如果 C++ 中不存在则创建新对象