Принудительный ход только семантики
Я относительно новичок в C++11, хотя я использовал предыдущие версии в течение многих лет. Это правильный способ обеспечить, чтобы объект был только подвижным?
class CResource
{
public:
CResource();
CResource(CResource &&);
CResource & operator=(CResource &&);
private:
CResource(const CResource &) = delete;
CResource & operator=(const CResource &) = delete;
void * m_pResource;
};
class CAcquireResource
{
public:
CResource && AcquireResource();
};
CResource && CAcquireResource::AcquireResource()
{
CResource res;
return std::move(res);
}
Отредактировано после комментариев от Себастьяна Редля и underscore_d
class CResource
{
public:
CResource();
CResource(CResource &&);
CResource & operator=(CResource &&);
};
class CAcquireResource
{
public:
CResource AcquireResource();
};
CResource CAcquireResource::AcquireResource()
{
CResource res;
return std::move(res);
}
Утверждения подтверждают...
#include <type_traits>
#define STR_NAME(s) #s
#define STATIC_ASSERT_NOCOPYASSIGN(clazz) \
static_assert(!std::is_copy_assignable<clazz>::value, \
STR_NAME(clazz) " is_copy_assignable");
#define STATIC_ASSERT_NOCOPYCONSTRUCT(clazz) \
static_assert(!std::is_copy_constructible<clazz>::value, \
STR_NAME(clazz) " is_copy_constructible");
#define STATIC_ASSERT_MOVEASSIGN(clazz) \
static_assert(std::is_move_assignable<clazz>::value, \
STR_NAME(clazz) " !is_move_assignable");
#define STATIC_ASSERT_MOVECONSTRUCT(clazz) \
static_assert(std::is_move_constructible<clazz>::value, \
STR_NAME(clazz) " !is_move_constructible");
#define STATIC_ASSERT_REFERENCECLASS(clazz) \
STATIC_ASSERT_MOVEASSIGN(clazz) \
STATIC_ASSERT_MOVECONSTRUCT(clazz) \
STATIC_ASSERT_NOCOPYASSIGN(clazz) \
STATIC_ASSERT_NOCOPYCONSTRUCT(clazz)
STATIC_ASSERT_REFERENCECLASS(CResource);
Они проходят с Visual Studio 2017.
1 ответ
Ваш метод обеспечивает только перемещение.
Однако простое существование конструктора перемещения / оператора присваивания уже подавляет генерацию конструктора копирования и оператора присваивания; явное удаление не требуется. Лишь немногие компиляторы в первые дни разработки C++11 не правильно реализовали эту часть.
Тем не менее, обратите внимание, что ваш AcquireResource
Код возвращает ссылку на локальную переменную и, следовательно, имеет неопределенное поведение. Вы должны вернуться по значению.