zoukankan      html  css  js  c++  java
  • 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
    知识共享,欢迎转载。
  • 相关阅读:
    Acwing 284.金字塔 (区间DP)
    Acwing 283.多边形 (区间DP)
    Acwing 277.饼干 (DP+排序不等式)
    Acwing 274.移动服务 (DP)
    Acwing 273.分级 (DP)
    Acwing 271.杨老师的照相排序 (DP)
    Acwing 272.最长公共上升子序列 (DP)
    Mybatis-缓存
    mybatis与spring整合
    mybatis-sql映射文件
  • 原文地址:https://www.cnblogs.com/lgh1992314/p/5834823.html
Copyright © 2011-2022 走看看