C++从静态对象的初始化顺序理解static关键字
问题
首先考虑一个全局变量的初始化顺序问题
在头文件1中:
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;
#endifInitializer.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内可见)的全局变量,这两个变量虽然变量名是一样的,但是地址是完全不同的。
输出如下:
C++从静态对象的初始化顺序理解static关键字的更多相关文章
- [C#解惑] #2 对象的初始化顺序
谜题 在上一篇C#解惑中,我们提到了对象的初始化顺序.当我们创建一个子类的实例时,总是会先执行基类的构造函数,然后再执行子类的构造函数.那么实例字段是什么时候初始化的呢?静态构造函数和静态字段呢?今天 ...
- Java对象的初始化顺序
new一个对象时,该对象的初始化顺序如下 : 父类中的静态成员变量 父类中的静态代码块 子类中的静态成员变量 子类中的静态代码块 父类中的非静态变量 父类中的非静态代码块 父类构造函数 子类中的非静态 ...
- java中静态代码块初始化顺序
(一)java 静态代码块 静态方法区别 一般情况下,如果有些代码必须在项目启动的时候就执行的时候,需要使用静态代码块,这种代码是主动执行的;需要在项目启动的时候就初始化,在不创建对象的情况下, ...
- [百度空间] [转] 在 Visual C++ 中控制全局对象的初始化顺序
from: http://blog.csdn.net/classfactory/archive/2004/08/07/68202.aspx 在 C++ 中,同一个翻译单位(.cpp文件)里的全局对象的 ...
- Java中静态数据的初始化顺序
Java的类中的数据成员中包含有静态成员(static)时,静态数据成员的初始化顺序是怎样的呢? [程序实例1] import java.util.*; import java.lang.*; imp ...
- C++ 类对象的初始化顺序 ZZ
C++构造函数调用顺序 1. 创建派生类的对象,基类的构造函数优先被调用(也优先于派生类里的成员类): 2. 如果类里面有成员类,成员类的构造函数优先被调用:(也优先于该类本身的构造函数 ...
- 静态数据成员(面向对象的static关键字)
静态数据成员: 在类内数据成员的声明前加上关键字static,该数据成员就是类内的静态数据成员.先举一个静态数据成员的例子. #include<iostream> using namesp ...
- java类对象的初始化顺序
在下面这个例子中,我们分别在父类和子类中测试了静态代码块.普通代码块.静态成员变量.普通成员变量.构造器.静态内部类. 一:代码块及变量测试 class Field{ public static St ...
- 什么是静态代码块?java中如何使用空参构造方法自动生成不同名字的对象,使用非静态的属性和静态属性有什么区别,原因是什么?如何理解static关键字
静态代码块?类加载就执行,最先执行 class demo{ static int num; static{ num=10; num*=3; System.out.println("haha& ...
随机推荐
- 设计模式之Strategy模式
策略模式属于对象的行为模式.其用意是针对一组算法,将每一个算法封装到具体的共同接口的独立类中,从而使得他们可以互相替换. 策略模式使得算法可以在不影响客户端的情况下发生变化. all in one “ ...
- linux内核netfilter连接跟踪的hash算法
linux内核netfilter连接跟踪的hash算法 linux内核中的netfilter是一款强大的基于状态的防火墙,具有连接跟踪(conntrack)的实现.conntrack是netfilte ...
- iOS原生分享功能
iOS_系统原生分享 - CSDN博客 通过UIActivityViewController实现更多分享服务 - 简书 UIActivity - UIKit _ Apple Developer Doc ...
- node.js 基于cheerio的爬虫工具,需要登录权限的爬虫工具
公司有过一个需求,需要拿一个网页的的表格数据,数据量达到30w左右:为了提高工作效率. 结合自身经验和网上资料.写了一套符合自己需求的nodejs爬虫工具.也许也会适合你的. 先上代码.在做讲解 'u ...
- Extjs6 组件浅谈
一.Component组件 一个 Ext JS 应用的界面由一个或多个叫做 组件的控件组成. 所有的组件都是 Ext.Component 类的子类,这个类可以允许参与包含实例化.渲染.自动大小和位置以 ...
- JS判断两个数字的大小
javascript中定义的var类型是弱类型,默认是String类型,在比较两个数字大小的时候默认比较的是两个字符串,比如,在比较10和2时,按数字做比较10是比2大,可是按默认的字符串比较时,第一 ...
- jQuery实现全选、不选和反选功能
jQuery结合Font Awesome字体图标实现全选.不选和反选功能 Font Awesome字体图标链接地址:http://www.fontawesome.com.cn/faicons/ 效果: ...
- 微信下载app需要点击右上角在浏览器中打开下载的问题
很多朋友是不是遇到过这样的问题,自家的app通过微信推广没办法直接下载,而是需要通过一个遮罩层来提示用户下载. 点击下载按钮提示点击右上角在浏览器中打开 这样的方式下载一个app是不是需要点击下载按钮 ...
- Python学习6——运算符
1.算数运算符 例1:给定一个三位数,给出每个位置上对应的参数: #方法01:当作数字来求 print("请输入一个三位数:") number = input() number = ...
- python 新手题目-文件读写-关键字判断
import os import json import re filename ="D:/pytest/2000/100/111.txt" f = open(filename,& ...