您的位置:首页 > 编程语言 > C语言/C++

effective C++笔记———不同编译单元内定义之non-local static对象的初始化次序问题(真拗口o(╯□╰)o)

2017-09-12 16:12 232 查看
首先解释两个概念:

1.编译单元:简单的说,按照C++标准,每一个.cpp文件就是一个编译单元,编译器不会编译.h头文件。

2.static对象:特点:生命周期从创建一直到程序结束为止。包括:全局(global)对象;定义域命名空间(namespace)作用域内的对象;在class内、函数内以及file作用域内被声明为static的对象。

函数内的static对象就叫做:local static对象。除此之外的static对象就是所谓的non-local static对象。

标题的意思,解释下来,就是在两份.cpp源码中,分别包含有一个non-local static对象,恰好这两个对象要初始化的时候又与另外一个有所关联,这时候就会存在一个初始化次序问题。举个例子就是,源码1中定义了nls(non-local static)对象A,源码2中定义了nls对象B,当B要初始化的时候会用到A的成员,如果在B要初始化的时候A还没有初始化,就会报错了。而C++中对于不同源码中的nls对象的初始化次序问题没有明确定义,也就是A和B初始化谁先谁后根本就是无解的。

解决办法:

按照effective C++所述,可以将每个nls对象搬到自己的专属函数内,在此函数内该对象被声明为static,最后函数返回指向这个新的static对象的引用。具体如下例:

class filesystem{
public:
...
std:size_t fun() const;//众多成员函数之一
...
};
extern filesystem A;


class directory{
public:
directory(params);
...
};
directory::directory(params)
{
...
std::size_t disks=A.fun();//使用A对象
...
}

directory B(params);


最后一行代码出现了标题所说的问题,除非A在B之前先被初始化,否则B的构造函数会用到还未初始化的A,但上文已经提到相关的初始化次序是一个无解的问题。

解决办法如下:

class filesystem{...};//同上
filesystem& A()       //这个函数用来替换A对象;它在filesystem class中可能是个static

{
static filesystem AA;//定义并初始化一个local static对象
return AA;           //返回一个referen指向上述对象
}


class directory{...};
directory::directory(params)
{
...
std::size_t disks=A().fun();
...
}
directory& B()
{
static directory BB;
return BB;
}


这样修改后,按照C++的标准,函数内的local static对象会在该函数被调用期间首次遇到该对象之定义式时被初始化,也就是调用函数A时AA对象将已经完成初始化,即解决了本文所述的次序问题。同时如果从未调用此函数,也绝不会产生构造和析构成本,非常划算。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐