RefPtr<T> - add move semantics

Add support for move semantics to the RefPtr<T> class. Implement a move constructor and a move assignment operator.
This commit is contained in:
Darragh Coy 2014-04-08 11:34:27 -07:00
parent 440a0adcde
commit 14b210a082
2 changed files with 62 additions and 6 deletions

View File

@ -82,10 +82,19 @@ NS_CC_BEGIN
template <typename T> class RefPtr
{
public:
RefPtr()
: _ptr(nullptr)
inline RefPtr()
:
_ptr(nullptr)
{
}
inline RefPtr(RefPtr && other)
{
_ptr = other._ptr;
other._ptr = nullptr;
}
inline RefPtr(T * ptr)
:
@ -113,7 +122,7 @@ public:
CC_REF_PTR_SAFE_RELEASE_NULL(_ptr);
}
inline RefPtr & operator = (const RefPtr<T> & other)
inline RefPtr<T> & operator = (const RefPtr<T> & other)
{
if (other._ptr != _ptr)
{
@ -125,13 +134,19 @@ public:
return *this;
}
inline RefPtr & operator = (std::nullptr_t other)
inline RefPtr<T> & operator = (RefPtr<T> && other)
{
CC_REF_PTR_SAFE_RELEASE_NULL(_ptr);
if (&other != this)
{
CC_REF_PTR_SAFE_RELEASE(_ptr);
_ptr = other._ptr;
other._ptr = nullptr;
}
return *this;
}
inline RefPtr & operator = (T * other)
inline RefPtr<T> & operator = (T * other)
{
if (other != _ptr)
{
@ -143,6 +158,12 @@ public:
return *this;
}
inline RefPtr<T> & operator = (std::nullptr_t other)
{
CC_REF_PTR_SAFE_RELEASE_NULL(_ptr);
return *this;
}
// Note: using reinterpret_cast<> instead of static_cast<> here because it doesn't require type info.
// Since we verify the correct type cast at compile time on construction/assign we don't need to know the type info
// here. Not needing the type info here enables us to use these operations in inline functions in header files when

View File

@ -279,6 +279,41 @@ void RefPtrTest::onEnter()
CC_ASSERT(false == (ref1 <= ref2));
CC_ASSERT(true == (ref1 >= ref2));
}
// TEST(moveConstructor)
{
auto someFunc = []() -> RefPtr<__String>
{
return __String::create("Hello world!");
};
// Note: std::move will turn the rvalue into an rvalue reference and thus cause the move constructor to be invoked.
// Have to use this because the compiler will try and optimize how we handle the return value otherwise and skip the move constructor.
RefPtr<__String> theString(std::move(someFunc()));
CC_ASSERT(theString->getReferenceCount() == 2);
CC_ASSERT(theString->compare("Hello world!") == 0);
__String * theStringPtr = theString;
theString.reset();
CC_ASSERT(theStringPtr->getReferenceCount() == 1);
CC_ASSERT(theStringPtr->compare("Hello world!") == 0);
}
// TEST(moveAssignmentOperator)
{
auto someFunc = []() -> RefPtr<__String>
{
return __String::create("Hello world!");
};
RefPtr<__String> theString(someFunc());
CC_ASSERT(theString->getReferenceCount() == 2);
CC_ASSERT(theString->compare("Hello world!") == 0);
theString = someFunc(); // No need to use std::move here, compiler should figure out that move semantics are appropriate for this statement.
CC_ASSERT(theString->getReferenceCount() == 2);
CC_ASSERT(theString->compare("Hello world!") == 0);
}
}
std::string RefPtrTest::subtitle() const