私はシンプルなスマートポインタを実装しています。これは、基本的にそれが扱うポインタへの参照の数を追跡します。移動コンストラクタとスマートポインタの移動割り当てを削除する必要がありますか?
私が知っているは移動のセマンティクスを実装することができますが、スマートなポインタをコピーすることは非常に安価であるとは思いません。特に、それは厄介なバグを生み出す機会をもたらしていると考えています。
ここに私のC++ 11のコードがあります(私はいくつかの本質的なコードを省略しました)。一般的なコメントも歓迎します。
#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_
いいえあなたはすべてをコピーしたい場合は、移動のメンバを宣言していません。それらを削除済みとして定義しないでください。 http://stackoverflow.com/questions/26489837/why-do-deleted-move-semantics-cause-problems-with-stdvector –
あなたは 'operator *'について正確に正しいです! Yikes!修正されました。 – blazs
'std :: shared_ptr'には、基本的な参照カウントメカニズムが並行性安全であるため、カスタム移動操作があります。したがって、カスタムの移動操作では、原子の増分を避けることができます。 – dyp