Chromium Code Reviews| Index: base/memory/ref_counted.h |
| diff --git a/base/memory/ref_counted.h b/base/memory/ref_counted.h |
| index 219437ed8d82b8b35835a6c3297d5f719f14c277..2942f76462aa57e8a6c1301968b92a7f2c5470ac 100644 |
| --- a/base/memory/ref_counted.h |
| +++ b/base/memory/ref_counted.h |
| @@ -14,6 +14,7 @@ |
| #ifndef NDEBUG |
| #include "base/logging.h" |
| #endif |
| +#include "base/move.h" |
| #include "base/threading/thread_collision_warner.h" |
| #include "build/build_config.h" |
| @@ -264,6 +265,7 @@ class RefCountedData |
| // |
| template <class T> |
| class scoped_refptr { |
| + TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_refptr) |
| public: |
| typedef T element_type; |
| @@ -286,6 +288,11 @@ class scoped_refptr { |
| AddRef(ptr_); |
| } |
| + template <typename U> |
| + scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) { |
| + r.ptr_ = nullptr; |
| + } |
| + |
| ~scoped_refptr() { |
| if (ptr_) |
| Release(ptr_); |
| @@ -323,6 +330,20 @@ class scoped_refptr { |
| return *this = r.get(); |
| } |
| + template <typename U> |
| + scoped_refptr<T>& operator=(scoped_refptr<U>&& r) { |
| + T* p = r.get(); |
| + r.ptr_ = nullptr; |
| + |
| + // In case |this == &r|, the above |r.ptr = nullptr;| line makes |
| + // |ptr_ == nullptr| so the following skips |Release(ptr_);| correctly. |
| + if (ptr_) |
| + Release(ptr_); |
| + |
| + ptr_ = p; |
|
dcheng
2015/04/13 03:45:38
I think this version is not safe against use-after
Kibeom Kim (inactive)
2015/04/13 09:57:53
Done. Added a simplified test case.
ScopedRefPtrT
|
| + return *this; |
| + } |
| + |
| void swap(T** pp) { |
| T* p = ptr_; |
| ptr_ = *pp; |
| @@ -334,6 +355,8 @@ class scoped_refptr { |
| } |
| private: |
| + template <typename U> friend class scoped_refptr; |
| + |
| // Allow scoped_refptr<T> to be used in boolean expressions, but not |
| // implicitly convertible to a real bool (which is dangerous). |
| // |