【发布时间】:2016-09-02 17:40:14
【问题描述】:
我正在实现一个简单的智能指针,它基本上跟踪对它处理的指针的引用数。
我知道我可以实现移动语义,但我认为这没有意义,因为复制智能指针非常便宜。特别是考虑到它带来了产生讨厌的错误的机会。
这是我的 C++11 代码(我省略了一些无关紧要的代码)。也欢迎普通的 cmets。
#ifndef SMART_PTR_H_
#define SMART_PTR_H_
#include <cstdint>
template<typename T>
class SmartPtr {
private:
struct Ptr {
T* p_;
uint64_t count_;
Ptr(T* p) : p_{p}, count_{1} {}
~Ptr() { delete p_; }
};
public:
SmartPtr(T* p) : ptr_{new Ptr{p}} {}
~SmartPtr();
SmartPtr(const SmartPtr<T>& rhs);
SmartPtr(SmartPtr<T>&& rhs) =delete;
SmartPtr<T>& operator=(const SmartPtr<T>& rhs);
SmartPtr<T>& operator=(SmartPtr<T>&& rhs) =delete;
T& operator*() { return *ptr_->p_; }
T* operator->() { return ptr_->p_; }
uint64_t Count() const { return ptr_->count_; }
const T* Raw() const { return ptr_->p_; }
private:
Ptr* ptr_;
};
template<typename T>
SmartPtr<T>::~SmartPtr() {
if (!--ptr_->count_) {
delete ptr_;
}
ptr_ = nullptr;
}
template<typename T>
SmartPtr<T>::SmartPtr(const SmartPtr<T>& rhs) : ptr_{rhs.ptr_} {
++ptr_->count_;
}
template<typename T>
SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T>& rhs) {
if (this != &rhs) {
if (!--ptr_->count_) {
delete ptr_;
}
ptr_ = rhs.ptr_;
++ptr_->count_;
}
return *this;
}
#endif // SMART_PTR_H_
【问题讨论】:
-
没有。如果您希望所有内容都是副本,则不要声明移动成员;不要将它们定义为已删除。 stackoverflow.com/questions/26489837/…
-
您对
operator*的看法完全正确!哎呀!已更正。 -
std::shared_ptr具有自定义移动操作,因为底层引用计数机制是并发安全的。因此,自定义移动操作可以避免原子增量。 -
好吧,如果你想知道一些好的方法,那就锁定
std::shared_ptr代码吧。 -
“复制一个智能指针很便宜”,但移动一个必须更便宜 - 不需要任何原子或锁定,因为我们没有触及计数?
标签: c++ c++11 smart-pointers move-semantics