背景:我所处的大代码环境中,运行全局构造函数的未定义顺序是有问题的。因此,我有一个定制类,用于将初始化延迟到第一次使用。它的所有魔力都发生在它的操作符*和运算符->函数中;它们是唯一定义的东西。它还在自身中存储一些状态,以使自动初始化功能可用.当然,这种状态必须是POD,所以整个类都是POD,这样在任何人的代码开始运行之前就可以完全设置它,这样所有的代码都可以在任何地方使用所有的全局,而不用担心全局还没有建立。
不久前,有人添加了一个私有的、从未定义的赋值操作符,这样类型就不会被分配给(它的设计无论如何都不会改变)。现在有人说这个类坏了,因为它不是POD。如果没有声明--但没有定义--我将其声明为“=删除”,我认为这样做更好。实际上,通过这种更改,std::is_pod<>::value返回类型的true。
但是,作为赋值运算符,是否阻止了某个类型成为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;
}发布于 2014-09-25 17:50:20
赋值运算符是否防止类型成为POD?
是。POD类型必须是琐碎的;因此必须是微不足道的可复制的;因此必须没有非平凡的复制或移动赋值运算符。
任何用户提供的操作符都是非平凡的,因此声明复制构造函数使类非平凡,因此非POD。
所以是全局初始化的?
不是的。任何可实例化的类型,POD或非,都可以是一个全局变量。
UPDATE:在评论中,您想问:
它可以静态地,而不是动态地初始化吗?
是的,因为它有一个普通的构造函数;只要初始化器是一个常量表达式。在您的示例中,{ "lazy" }是一个常量表达式,因此可以静态初始化LazyString。
这里的重要特性是它有一个简单的构造函数,而不是POD。吊舱意味着它也满足各种其他要求,与初始化无关。
发布于 2014-09-25 18:13:39
C++对具有静态存储持续时间的非局部变量有几个初始化阶段(全局变量属于此类别)--不管该类型是否为POD。
前两种类型的初始化必须在动态初始化之前进行。动态初始化是初始化顺序难以设置的情况。有些动态初始化是无序的,有些是在转换单元内排序的,等等。
即使您的全局变量不是POD,您也可以确保在任何动态init之前都会发生零初始化。
有关详细信息,请参阅C++11 3.6.2“非局部变量的初始化”。
https://stackoverflow.com/questions/26044494
复制相似问题