effective C++笔记———不同编译单元内定义之non-local static对象的初始化次序问题(真拗口o(╯□╰)o)
2017-09-12 16:12
375 查看
首先解释两个概念:
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对象的引用。具体如下例:
最后一行代码出现了标题所说的问题,除非A在B之前先被初始化,否则B的构造函数会用到还未初始化的A,但上文已经提到相关的初始化次序是一个无解的问题。
解决办法如下:
这样修改后,按照C++的标准,函数内的local static对象会在该函数被调用期间首次遇到该对象之定义式时被初始化,也就是调用函数A时AA对象将已经完成初始化,即解决了本文所述的次序问题。同时如果从未调用此函数,也绝不会产生构造和析构成本,非常划算。
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对象将已经完成初始化,即解决了本文所述的次序问题。同时如果从未调用此函数,也绝不会产生构造和析构成本,非常划算。
相关文章推荐
- effective C++笔记———不同编译单元内定义之non-local static对象的初始化次序问题(真拗口o(╯□╰)o)
- effective C++笔记———不同编译单元内定义之non-local static对象的初始化次序问题(真拗口o(╯□╰)o)
- effective C++笔记———不同编译单元内定义之non-local static对象的初始化次序问题(真拗口o(╯□╰)o)
- effective C++笔记———不同编译单元内定义之non-local static对象的初始化次序问题(真拗口o(╯□╰)o)
- effective C++笔记———不同编译单元内定义之non-local static对象的初始化次序问题(真拗口o(╯□╰)o)
- effective C++笔记———不同编译单元内定义之non-local static对象的初始化次序问题(真拗口o(╯□╰)o)
- effective C++笔记———不同编译单元内定义之non-local static对象的初始化次序问题(真拗口o(╯□╰)o)
- 条款4:不同编译单元内的non-local static对象的初始化次序
- 转:不同编译单元内定义的non-local static 对象的初始化顺序
- 不同编译单元内定义的non-local static 对象的初始化顺序
- 不同编译单元内定义的non-local static 对象的初始化顺序
- 对象被使用之前先被初始化--定义于不同编译单元内的non-local tatic对象
- 不同编译单元内定义之non-local static 对象
- 不同编译单元内的非局部静态对象的初始化次序问题
- effective C++笔记之条款31、32: 千万不要返回局部对象的引用,也不要返回函数内部用new初始化的指针所指对象的引用、尽可能地推迟变量的定义
- C++不同编译单元内定义的非局部静态对象的初始化顺序
- non-local static对象初始化【EC++笔记】
- effective c++ 跨编译单元之初始化次序 笔记
- non-local static对象初始化顺序
- JAVA中定义对象属性为int类型初始化问题