【问题标题】:Enforcing move only semantics强制仅移动语义
【发布时间】:2018-04-13 10:04:55
【问题描述】:

我对 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 的 cmets 之后编辑

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。

【问题讨论】:

  • afaics: 做deletedprivate 的东西是没有意义的;这只会给用户带来另一个多余的错误。见here。从语义上考虑,您希望公众知道他们不能使用已删除的方法。
  • 谢谢,这是我在 = delete 不存在时编写的代码的回溯。我会改变它。我更担心我是否只强制移动?

标签: c++11 move-semantics class-design deleted-functions


【解决方案1】:

你的方法强制只移动。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-16
    相关资源
    最近更新 更多