为什么在移动操作后
observer_ptr
没有归零?
它在默认构造中正确设置为nullptr,这确实有意义(并防止指向垃圾).
因此,当std :: move()’时,它应该被归零,就像std :: string,std :: vector等.
这将使它成为原始指针有意义的几个上下文中的一个很好的候选者,以及在具有原始指针数据成员的类上自动生成移动操作,如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); } };
使用“哑”智能指针,它是null-on-default-construction和null-after-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); } };
这就是为什么有一个愚蠢的,非拥有的智能指针是有用的,这个指针在移动后是空的,就像tidy_ptr
但是observer_ptr只是null-on-default-construction,所以如果它是标准化的,那么声明一个函数来获取一个非拥有的指针会很有用,但它对上面那个类没用,所以我’ ll仍然需要另一个非拥有的哑指针类型.有两个非拥有的哑智能指针类型似乎比没有没有!