C++从静态对象的初始化顺序理解static关键字
2017-07-24 17:41
627 查看
问题
首先考虑一个全局变量的初始化顺序问题 在头文件1中:
在头文件2中:
源文件中包含了头文件1和头文件2,这种情况下a和b可能的值是什么呢?
extern int b; int a = b + 1;
在头文件2中:
extern int a; int b = a + 1;
源文件中包含了头文件1和头文件2,这种情况下a和b可能的值是什么呢?
虽然在开发过程一般不会出现上述这种情况,但是这核心的是一个全局变量初始化顺序的问题,这个问题在团队开发过程可能会碰到。
可以使用static的特性来解决此问题,static关键字作用一般有以下几点:
1. 静态全局变量,变量在该翻译单元是可见的,但是在其他翻译单元中是不可见的(翻译单元暂时理解为源文件,后文解析)。如下:
//源文件1中 static int n; //源文件2中 extern int n;//这里编译无错,但链接出错,因为源文件1中的n是外部不可见的
2. 静态局部变量,变量虽然是一个局部变量,但是它在全局变量区分配内存,该变量在局部可见,并且只初始化一次。
3. 静态函数,和静态全局变量一样,该翻译单元可见,外部不可见。
4. 类中静态成员变量,变量需要在类外部声明,所有类的对象共用一个静态成员变量。
5. 类中静态成员函数。
解决方式
Initializer.h中:
#ifndef INITIALIZER_H #define INITIALIZER_H #include <iostream> extern int x; extern int y; class Initializer { static int initCount; public: Initializer() { std::cout << "Initializer()" << std::endl; if (initCount++ == 0) { std::cout << "performint initialization" << std::endl; x = 100; y = 200; } } ~Initializer() { std::cout << "~Initializer()" << std::endl; if (--initCount == 0) { std::cout << "performint cleanup" << std::endl; } } void testFun() { std::cout << "testFun"<< initCount << std::endl; } private: }; static Initializer init; #endif
Initializer.cpp
#include "Initializer.h" int x; int y; int Initializer::initCount;
其他cpp文件只需要包含头文件即可自动解决x和y的初始化顺序问题。
#include "Initializer.h"
在Initializer.h定义了一个静态全局变量,这个变量在一个翻译单元是内部可见的,所以Initializer.cpp和所有包含Initializer.h的源文件中都会又有一个init变量,这个变量虽然名称相同,但是每个翻译单元的init变量地址是不同的。不理解的话可以考虑下面代码的输出:
header.h中:
static int nCount = 1;
fun.cpp中:
#include "header.h" #include <iostream> void fun() { std::cout << "enter fun:" << &nCount << "\t" << nCount << std::endl;
nCount++; std::cout << "leave fun:" << &nCount << "\t" << nCount << std::endl;
}
main.cpp中:
#include "header.h" #include <iostream> extern void fun(); int main() { std::cout << "enter main:" << &nCount << "\t" << nCount << std::endl;
fun(); std::cout << "leave main:" << &nCount << "\t" << nCount << std::endl;
return 0; }
header.h中定义了一个静态全局变量,fun.cpp是一个翻译单元,编译fun.cpp时,nCount是一个内部可见(fun.cpp内可见)的全局变量。编译main.cpp时,nCount是一个内部可见(main.cpp内可见)的全局变量,这两个变量虽然变量名是一样的,但是地址是完全不同的。
输出如下:
相关文章推荐
- 什么是静态代码块?java中如何使用空参构造方法自动生成不同名字的对象,使用非静态的属性和静态属性有什么区别,原因是什么?如何理解static关键字
- 黑马程序员--面向对象(二)static关键字、静态代码块、对象的初始化过程
- java--面向对象(static关键字、main、静态什么时候使用、静态代码块、对象的初始化过程)
- Java中初始化对象的顺序,静态代码块的用法以及Static的用法详解
- Java中初始化对象的顺序,静态代码块的用法以及Static的用法详解
- 黑马程序员 笔记(六)——面向对象(static关键字、静态、main函数、、帮助文档、对象的调用和初始化、单例)
- Java中初始化对象的顺序,静态代码块的用法以及Static的用法详解
- 面向对象中的构造方法以及关键字static的理解
- java中类/对象的初始化顺序以及静态代码块的使用
- 面向对象(二)——操作符重载 & 关键字this & 静态成员static
- Java中This ,Static,对象,对象的引用 等关键字的理解
- 16-面向对象(static关键字-什么时候用) 面向对象-Static难点 18-面向对象(构造代码块).(静态代码块)
- 面向对象--static静态关键字
- Java静态方法,静态变量,初始化顺序 static
- [转]Java中静态代码块及对象的初始化顺序
- C#多态;父类引用指向子类对象;new和override的区别;new、abstract、virtual、override,sealed关键字区别和使用代码示例;c#类的初始化顺序
- 构造函数 ;构造函数的执行顺序。静态字段的初始化顺序。new关键字为我们做了什么。
- 继承与初始化(static对象初始化顺序)
- Java Static静态关键字理解
- (5)this和static关键字及对象初始化过程