C++ 11:赋值运算符是否阻止某个类型成为POD,从而进行全局初始化?

jor*_*own 5 c++ initialization pod c++11

背景:我在一个大代码环境中,运行全局构造函数的未定义顺序是有问题的.所以我有一个自定义类,旨在延迟初始化直到首次使用.它的所有魔力都发生在它的运算符*和operator->函数中; 他们是唯一定义的东西.它还在其自身内存储一些状态,以使自动初始化功能可用.当然,该状态必须是POD,所以整个类都是POD,所以它可以在任何人的代码开始运行之前完全设置,这样所有代码都可以在任何地方使用所有全局变量,而不必担心全局变形尚未成立.

有一段时间后,有人添加了一个私有的,从未定义过的赋值运算符,因此永远不会将该类型赋值给它(它的设计无论如何都不会改变).现在有人说这堂课已经坏了,因为它不是POD.如果不是声明但未定义,我将其声明为"=删除",我认为这更好.实际上,通过该更改,std :: is_pod <> :: value将返回类型的true.

但是,作为赋值运算符会阻止某个类型成为POD吗?我认为要求只是它必须只有公共数据成员,没有虚拟方法,没有构造函数或析构函数.

更重要的是我的情况:是否存在一个永不定义的赋值运算符会阻止该类在全局初始化时与所有其他全局POD一起初始化?

减少的例子:

struct LazyString {
  const char *c_str;

  bool has_been_inited;
  string *lazy_str_do_not_use_directly;

  string &operator*() { return *get(); }
  string *operator->() { return get(); }

 private:
  string *get() {
    // The real code uses a mutex, of course, to be thread-safe.
    if (!has_been_inited) {
      lazy_str_do_not_use_directly = new string(c_str);
      has_been_inited = true;
    }
    return lazy_str_do_not_use_directly;
  }

  // Does this make the class non-POD?
  // If so, does that mean that global variables of this type
  // will not be initialized at global-initialization time, that wonderful
  // moment in time where no code has yet been run?
  void operator=(const LazyString&);

  // If I do this instead, it breaks C++03 compatibility, but is this somehow better?
  void operator=(const LazyString&) = delete;
};

LazyString lazy = { "lazy" };

int main(int argc, char *argv[]) {
  std::cout << *lazy;
}
Run Code Online (Sandbox Code Playgroud)

Mik*_*our 6

赋值运算符是否阻止类型为POD

是.POD类型必须是微不足道的 ; 所以必须是可以轻易复制的 ; 所以必须没有非平凡的副本或移动赋值运算符.

任何用户提供的运算符都是非平凡的,因此声明复制构造函数会使类非常重要,因此非POD.

因此被全球初始化?

不可以.任何可实例化的类型,POD与否,都可以是全局变量.

更新:从评论中,您的意思是:

是静态的,而不是动态的,初始化?

是的,因为它有一个简单的构造函数; 只要初始化器是一个常量表达式.在您的示例中,{ "lazy" }是一个常量表达式,因此LazyString可以静态初始化.

这里的重要特征是它有一个简单的构造函数,而不是它的POD.POD意味着它还满足与初始化无关的各种其他要求.