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

问题描述 投票:15回答:5

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

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&&),因为它可以用于两种目的。

c++ c++11 copy move-semantics
5个回答
23
投票

根据这张图表(Howard Hinnant):

meow

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

虽然,在我看来,最可读的方式是=delete复制构造函数和复制赋值运算符。


4
投票

Please don't try to find "the most concise way" to write a piece of code.

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

在你的情况下,如果你做了这些删除的一个子集,或使用其他一些“聪明”的技巧 - 作为一个阅读你的代码的人,我有点可能不会流行,而不是注意到你实际上是想要获得所有副本和移动语义删除。我会感到困惑,以为你正在尝试做别的事情。事实上,如果我是你,我甚至会考虑添加评论说:

/* 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 ++的杰出人物霍华德·亨南特(Howard Hinnant)就此问题发表了this to say

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


3
投票

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

#include <boost/core/noncopyable.hpp>

class X: private boost::noncopyable
{
};

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


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
}

-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;
© www.soinside.com 2019 - 2024. All rights reserved.