【问题标题】:Why should I delete move constructor and move assignment operator in a singleton?为什么要在单例中删除移动构造函数和移动赋值运算符?
【发布时间】:2014-07-09 09:18:17
【问题描述】:

我有以下单例策略类实现:

template <typename T>
class Singleton
{
    Singleton(){}; // so we cannot accidentally delete it via pointers
    Singleton(const Singleton&) = delete; // no copies
    Singleton& operator=(const Singleton&) = delete; // no self-assignments
    Singleton(Singleton&&) = delete; // WHY?
    Singleton& operator=(Singleton&&) = delete; // WHY?
public:
    static T& getInstance() // singleton
    {
        static T instance; // Guaranteed to be destroyed.
                       // Instantiated on first use.
                       // Thread safe in C++11
        return instance;
    }
};

然后我通过奇怪的重复模板模式 (CRTP) 使用它

class Foo: public Singleton<Foo> // now Foo is a Singleton
{
    friend class Singleton<Foo>;
    ~Foo(){}
    Foo(){};
public:
// rest of the code
};

我不明白为什么要删除移动构造函数和赋值运算符。你能给我一个例子,如果我不删除(根本不定义)移动 ctor 和赋值运算符,我最终会破坏单例吗?

【问题讨论】:

  • 你应该在哪里读到的?
  • 没有理由,你不必那样做。
  • @LightnessRacesinOrbit 在这里例如:stackoverflow.com/a/15187331/3093378 我记得在其他一些代码示例中看到过它,尽管我不记得了。我想知道为什么,因为我认为如果我删除复制 ctor,则不会隐式定义移动 ctor
  • 您实际分配/移动的用例是什么,否则要求为这种情况提供语言定义?
  • @πάνταῥεῖ 我试图看看我是否真的需要将其声明为已删除(即,如果没有,是否有可能通过以某种方式在向量中移动 @ 返回的对象来打破单例模式987654324@,即使实例失效。)

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


【解决方案1】:

如果你声明了一个复制构造函数(即使你在声明中将它定义为deleted),也不会隐式声明任何移动构造函数。参照。 C++11 12.8/9:

如果类X的定义没有明确声明移动构造函数,当且仅当

— X 没有用户声明的复制构造函数,

——……

由于您确实有一个用户声明的复制构造函数,因此如果您不声明一个移动构造函数,则根本就不会有移动构造函数。所以你可以完全摆脱移动构造函数声明定义。移动赋值运算符也是如此。

【讨论】:

  • @vsoftco:有时,了解事物运作方式的最简单方法是阅读规则……它们可能有点令人生畏,但我强烈推荐 :-)
  • 是的,我试过了,但没有标准,也没有找到关于何时不隐式声明移动 ctor 的确切规则。例如这里en.cppreference.com/w/cpp/language/move_constructor我没有意识到当你delete复制ctor时你实际上是在“声明”它:)
  • @vsoftco:是的,是的,你必须特别注意语言。用户提供的、用户声明的、用户定义的、隐式定义的、隐式声明的……你可以得到标准from GitHub的当前工作草案。
  • 哦,我不知道,非常感谢你的链接,我不想付钱:)
  • +1 我的观点与您的回答一致,但更强烈:作为风格指南,我建议移动成员永远不要被删除。充其量删除它们是多余的。在最坏的情况下,它们的删除是一个错误(但在这种情况下不是)。因此,在代码审查中,如果我看到删除的 move 成员,这会迫使我检查以确保我们不在错误区域。
猜你喜欢
  • 2016-05-19
  • 2017-05-15
  • 1970-01-01
  • 2020-01-23
  • 1970-01-01
  • 2020-09-06
  • 1970-01-01
  • 2017-01-17
  • 2017-12-11
相关资源
最近更新 更多