最简洁的方法来禁用复制和移动语义

时间:2018-02-19 11:15:57

标签: c++ c++11 copy move-semantics

以下肯定有效,但非常繁琐:

T(const T&) = delete;
T(T&&) = delete;
T& operator=(const T&) = delete;
T& operator=(T&&) = delete;

我正在尝试发现最简洁的方法。以下是否有效?

T& operator=(T) = delete;

更新

请注意,我选择的是T& operator=(T)而不是T& operator=(const T&)T& operator=(T&&),因为它可以同时满足这两个目的。

5 个答案:

答案 0 :(得分:22)

根据此图表(Howard Hinnant):

meow

最简单的简洁方式是=delete移动赋值运算符(或移动构造函数,但它可能会导致注释中提到的问题)。

尽管如此,在我看来,可读方式是=delete 两种复制构造函数和复制赋值运算符。

答案 1 :(得分:4)

请不要试图找到最简洁的方式"写一段代码。

如果没有一种明显的表达形式也是非常简洁的 - 不要寻求不要以语言 - 律师的方式去写少数几个字。为什么?想想阅读代码的人:如果你需要查阅标准来实现你的代码做你想做的事情那么 - 那么代码的读者也是如此。除了他们不知道你想要实现什么;所以他们不会参考标准;所以他们只会对你的代码所做的事情感到困惑。或者 - 有些人会得到它而有些人不会。 *

在你的情况下,如果你做了这些删除的一个子集,或者使用其他一些"聪明的"诀窍 - 作为一个阅读你的代码的人,它有点可能我不会流行,而不是注意到你实际上试图让所有的复制和移动语义被删除。而且我会感到困惑,以为你正在尝试做别的事情。事实上,如果我是你,我甚至会考虑添加评论说:

/* Disabling copy and move semantics because XYZ */
T(const T&) = delete;
T(T&&) = delete;
T& operator=(const T&) = delete;
T& operator=(T&&) = delete;

这更加繁琐",但会使你的意图/动机对你未来的读者绝对清楚。

还有一个问题是" XYZ"原因是。有些人认为删除移动成员没有充分的理由,这样做通常是个坏主意。 C ++的杰出人物霍华德·亨南特就此问题this to say

* - 根据我拼写here原则的变体。

答案 2 :(得分:3)

我更愿意继承boost::noncopyable,从而立即明确意图,并将细节委托给值得信赖的图书馆。

#include <boost/core/noncopyable.hpp>

class X: private boost::noncopyable
{
};

它涉及添加一个依赖项,但是如果你对此感到满意,它可以说是一种非常简洁和富有表现力的方法来实现它。

答案 3 :(得分:2)

你可以写一个简单的struct并从中继承:

struct crippled
{
    crippled() = default;

    crippled(const crippled&) = delete;
    crippled(crippled&&) = delete;

    crippled& operator=(const crippled&) = delete;
    crippled& operator=(crippled&&) = delete;
};

用法:

struct my_class : crippled
{

};

int main()
{
    my_class a;
    auto b = a; // fails to compile
}

答案 4 :(得分:-1)

我相信在这种情况下,宏实际上更具可读性:

#define NOT_COPYABLE( TypeName ) \
TypeName ( TypeName const& ) = delete; \
TypeName & operator = ( TypeName const& ) = delete;

#define NOT_MOVEABLE( TypeName ) \
TypeName ( TypeName && ) = delete; \
TypeName & operator = ( TypeName && ) = delete;