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). |
// |