0

我对 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);
}

根据 Sebastian Redl 和 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。

4

1 回答 1

3

您的方法强制执行只移动。

但是,仅仅存在移动构造函数/赋值运算符就已经抑制了复制构造函数和赋值运算符的生成;不需要显式删除。在 C++11 草案的早期,只有少数编译器没有正确实现这部分。

但是,请注意,您的AcquireResource代码返回对局部变量的引用,因此具有未定义的行为。你应该按价值返回。

于 2018-04-13T10:28:36.303 回答