non-local static 变量初始化顺序不确定,带来的问题

所谓static对象,其寿命从被构造出来直到程序结束为止,因此stack和heap-based对象都被排除。这种对象包括global对象、定义于namespace作用域内的对象,classes内、在函数内、以及在file作用域内被声明为static的对象。函数内的static对象称为local static对象(因为它们对函数而言是local),其他static对象成为non-local static对象,在程序结束时static对象会被自动销毁,也就是他们的析构函数会在main()结束时被调用

    c++对“定义于不同的编译单元内的non-local static对象”的初始化次序并无明确定义。

 

   为了更清晰的理解上述文字,特意写了一个错误的实例,代码如下:

//a1.cpp
#include <fstream>
#include <iostream>
#include "a3.cpp"
using namespace std;
Write a;
int main()
{
	
	system("pause");
	return 0;
}
//a2.cpp
#include <fstream>
using namespace std;
extern ofstream out("a6.txt");
//a3.cpp
#include <fstream>
using namespace std;
extern ofstream out;
class Write
{
public:
	Write()
	{
		out<<"a4.txt";
	}
	
};

上述代码,a2.cpp中,定义了全局变量 out,a3.cpp中定义了一个类 Write,它的构造函数初始化依赖于 out,因为2个文件的便宜顺序是不确定的,所以,很有可能 当Write()调用的时候,out全局变量并没有被初始化,造成程序错误。

 

案例2:

 

先上代码:

//FileSystem.h
#include <iostream>
class FileSystem
{
public:
	FileSystem(int a):num(a)
	{
	}
	std::size_t numDisks() const;
	
private:
	int num;
	
};
//FileSystem.cpp
#include "FileSystem.h"
std::size_t FileSystem::numDisks() const 
{
	return num;
}
//Directory.h
#include <iostream>
#include "FileSystem.h"
class Directory
{
public:
	Directory();
	int display();
private:
	int a;
};
//Directory.cpp
#include "Directory.h"
extern FileSystem tfs;
Directory::Directory()
{
	std::size_t disks = tfs.numDisks();
	a = disks;
}
int Directory::display()
{
	return a;
}
Directory a;
//Y.cpp
#include "FileSystem.h"
extern FileSystem tfs(10);
//X.cpp
#include "Directory.h"
#include <iostream>
using namespace std;
extern Directory a;
int main()
{
	
	cout<<a.display()<<endl;
	system("pause");
}

代码中 Directory对象的初始化依赖于 全局对象FileSystem tfs,因为C++“对定义于不同的编译单元内的non-local static对象”的初始化相对次序并没有明确定义,所以很有可能在 Y.cpp里的变量tfs初始化之前,先初始化 Directory.cpp里的对象a,则a就得不到我们想要的值。

  因为C++保证,函数内的local static对象会在“该函数被调用期间”“首次遇到该对象的定义式”时被初始化,所以代码修改如下:

//FileSystem.h
#include <iostream>
class FileSystem
{
public:
	FileSystem(int a):num(a)
	{
	}
	std::size_t numDisks() const;
	
private:
	int num;
	
};
//FileSystem.cpp
#include "FileSystem.h"
std::size_t FileSystem::numDisks() const 
{
	return num;
}


//Directory.h
#include <iostream>
#include "FileSystem.h"
class Directory
{
public:
	Directory();
	int display();
private:
	int a;
};
//Directory.cpp
#include "Directory.h"
extern FileSystem& tfs();
Directory::Directory()
{
	std::size_t disks = tfs().numDisks();  //tfs()函数返回一个FileSystem& 对象
	a = disks;
}
int Directory::display()
{
	return a;
}
Directory& tempDir()
{
	static Directory td;
	return td;
}
//Y.cpp
#include "FileSystem.h"
FileSystem& tfs()
{
	static FileSystem fs(10); //在一个函数里,返回静态对象
	return fs;
}
//X.cpp
#include "Directory.h"
#include <iostream>
using namespace std;
extern Directory& tempDir();
Directory a=tempDir();
int main()
{
	
	cout<<a.display()<<endl;
	system("pause");
}


Keep it simple!
作者:N3verL4nd
知识共享,欢迎转载。
原文地址:https://www.cnblogs.com/lgh1992314/p/5834823.html