2011-04-11 85 views
2

我有一个全局变量,它是一个类的实例。这个类在其构造函数(directX)中创建了一个图像。C++全局变量使用寿命

问题是我在运行时遇到了访问冲突,但代码编译了。我认为问题在于在winmain函数中完成初始化之前调用类构造函数。

,所以我想知道什么是

  1. 有没有人遇到过这个问题和解决方案的了解。

  2. 什么是全局的生命周期,我知道函数中声明的变量在它返回后会丢失,并且编译器会通过代码查看是否所有匹配项都匹配,这就是为什么我们必须创建函数原型,但是全局的进入等式。

+0

afaik全局应该支持程序的整个生命周期,但没有代码,这很难说,如果这是你的情况。 – 2011-04-11 10:25:12

+0

你的DLL是全局变量吗? – paperjam 2011-04-11 10:30:13

+0

@paperjam winmain在一个循环中调用一个游戏运行函数,代码在那里,来自一本书,用于分离初始化和游戏代码,但意味着事物必须是全局的,因为它们在游戏运行函数调用。如果你有一个想法,打开一个更好的设置 – Skeith 2011-04-11 10:32:41

回答

4

你可能想要看的东西像singleton pattern,如果你真的想有一个全球性的一个实例,初始化完成后,可以进行初始化(基本上,图像将被修建的第一次引用它之后你会使用预先构建的版本)。

在调用winmain之前构造全局变量(以未定义的顺序)。他们留在那里,直到你的程序退出(在这一点上,我相信析构函数被称为未定义的顺序)..

另一个(可能更简单)替代你可以使用将是改变你的全球从一个类的实例一个指向它...然后你会碰到这样的:

// global... 
MyGlobalClass *bigGlobalImageHolder; 

// Winmain 
// Perform directX setup (don't know what that is) 
// Create the image class 
bigGlobalImageHolder = new MyGlobalClass(); 


// do the rest of your stuff... I'm guessing enter some kind of event loop 

// clean up your global 
delete bigGlobalImageHolder; 
// exit your winmain (and application) 

然后到处您目前引用全局,你可以通过一个指针,而不是引用它..

// so 
bigGlobalImageHolder.GetImage(); 
// becomes 
bigGlobalImageHolder->GetImage(); 
+0

如果我没有记错,析构函数的调用顺序与调用构造函数的顺序相同,但相反。它是以未定义的顺序调用的构造函数。即使如此,如果在同一个文件中定义了两个全局变量,那么第一个变量也将首先被初始化,并最终被销毁。 – Septagram 2011-04-11 10:32:21

+4

单身人士只适用于非常罕见的情况,如果您真的需要将某个类限制为单个实例,这听起来不像这里 - 只需要全局访问的对象。在C++中,单例有很多自己的问题(特别是线程安全创建和控制销毁顺序),这使得它们很难正确实现。我会建议反对单身人士,但建议您在'main'中创建对象时使用+1。 – 2011-04-11 11:15:12

0

它看起来你正在经历“静态初始化” n命令失败“。

检查这个this和以下常见问题。

如上所述,您可能需要实施一种或另一种Singleton

0
  1. 我遇到了这个问题;无论使用哪种代码,class constructor都应在class constructor启动之前初始化。假设其他变量也是全局变量,那么应该先调用它们的构造函数。尽管变量的构造函数以未定义的方式调用,但您可以使用的只是一些小的工作,可以从最小依赖到最依赖的顺序在相同文件中定义相关全局变量。
  2. 全球的寿命等于你的程序的寿命
0

全球静数据的生命周期是应用程序的生命周期。但是,在正常终止时,析构函数将会运行

问题在于,初始化/销毁发生的顺序并不总是确定性的,当然也不是可移植的(即,取决于平台,例如运行时链接器)。

共享对象(动态链接)的情况最糟糕。有些平台允许使用链接器标志来指定共享对象的“优先级”(以便可以影响静态初始化顺序);其他平台(例如AIX gcc,HP/UX)需要特殊的编译器属性才能将静态过程标记为“dll初始化例程”。


总之:除了通过存取函数外,不依赖于静态数据。存取器功能可能是这样的:

static int _myinternalvar = 3; 
static int GetMyInternalVar() 
{ 
     return _myinternalvar; 
} 

这样,你知道肯定执行函数之前的静态已初始化。访问者是唯一可以访问数据的函数,您可以在其范围内声明静态(添加封装)。