全局变量和作用域 - C++

5

我在全局变量的使用上遇到了一些问题。我正在使用Visual Studio 2008和标准C++。

我有两个项目,一个是静态库,另一个是使用该库的测试程序。我在global.h中定义了一个全局变量,如下:

#ifndef GLOBAL_H
#define GLOBAL_H

#include <string>

extern std::string globalWord;

#endif // GLOBAL_H!

我有一个global.cpp文件,其中我正在初始化这个变量。这个变量在我的库项目中被使用。我从测试项目中为这个变量设置了一个值,但是这个值没有反映在库项目中。
我已经进行了调试,并且在测试项目中显示了新值,但是当控制权到达库项目时,这个变量的值为空。所以这个全局变量的作用域只限于它所属的项目吗?
还是有更好的方法?我不想修改我的函数或构造函数参数来传递这个值。
任何帮助都将是伟大的。
编辑:
以下是global.cpp中声明这个变量的方式:
#include <string>
#include "../global.h"

std::string globalWord = "";

这是我在我的库中使用它的方式。
#include "../global.h"
string text = globalWord;

谢谢


展示所有的代码。这应该按照你描述的方式工作,所以肯定是其他地方出了问题。 - paxdiablo
这是一个静态库。我已经在测试项目的“项目依赖项”中设置了它。 - Navaneeth K N
在我的测试项目中,我将这个全局变量设置为某个值,比如 "Foo"。我需要在库中获取这个值。是的,主程序已经开始运行了。我在测试项目中使用 UnitTest++,这是尝试测试一个方法而不修改它参数的一种方式。感谢帮助。 - Navaneeth K N
修改.exe文件并未在dll中反映出来。我的解决方案是将全局文件从lib移动到dll并进行导出。 - Ismael
另一种方法是创建一个只包含字符串的类,但可以添加一个构造函数并在那里设置一个断点,这样您就知道它何时被创建。 - Ismael
显示剩余9条评论
4个回答

9

不要使用全局变量。真的不行。如果你必须要有全局可访问的数据,最好使用一个返回globalWord的全局函数,像这样:

std::string globalWord()
{
    static std::string word("Hi Mom");
    return word;
}

这样做可以避免初始化顺序问题(请参考Effective C++第4条)。

谢谢。所以字符串变量将一直存在到程序结束?我需要设置它的值。那我可以有一个SetGlobalWord方法吗?如果可以,那么我应该将值设置到哪个变量中呢? - Navaneeth K N
1
@Matt:只要你将返回值更改为引用,我就点赞。Appu特别需要能够更改该值。 - j_random_hacker
@j_random_hacker,自从何时起,G++可以自动执行这个操作?即使是全局变量,线程问题仍然存在。(毕竟,函数静态变量只是作用域为全局的变量。) - strager
@strager:J_random_hacker所指的是初始化问题。静态函数变量在第一次使用时被初始化(不像全局变量),因此在多线程环境中可能会出现问题。G++显式地添加了代码来保证变量只被初始化一次。 - Martin York
定义一个全局对象(具有getter/setter),并包含所有这些变量,怎么样? - wmac
显示剩余5条评论

6
使用 "extern" 关键字,告诉编译器实际变量存在于其他地方。您还应该在一个且仅一个位置创建同名但没有 extern 的变量。如果定义了两个变量,则通常会从链接器获得错误,但如果一个在库中而另一个不在,则可能无法解决问题。
编辑:确保 global.cpp 只在库或测试程序中存在,而不是两者都存在。

3
问题很可能是初始化顺序的问题。当程序被链接时,有两个地方使用了globalWord进行初始化:
  1. text的初始化("string text = globalWord;")
  2. globalWord本身的初始化
不幸的是,C++标准没有规定来自不同模块的全局变量初始化的顺序。类似于Matt的回答,使用函数或简单类(例如单例)访问全局值是强制特定初始化顺序的常用方法。 C++ FAQ中稍微讨论了一下这个问题——如果您计划在程序中修改globalWord,则情况比他们讨论的更加复杂,因为他们似乎没有解决设置隐藏在“首次使用构造”函数后面的值的问题。通常需要像单例类那样的东西

这如何解释调试器在不同上下文中显示不同内容的情况? - Mark Ransom
这是个好主意,但是Appu刚刚回复了我的评论,说“text”是一个在main()启动后初始化的本地变量,在这一点上,所有全局变量都已经被初始化了(以某种顺序)。因此,据我所知,静态初始化顺序问题不能是这里的问题。 - j_random_hacker
@Mark- 你说得对 - 这个答案可能无法解释他所描述的行为(尽管调试描述对我来说不是完全清楚)。我基于代码片段回答的 - 希望它们是通过剪贴板从实际代码中复制的。 - Michael Burr

2

您所描述的行为似乎更像是在使用DLL时出现的问题,但您说您的库是静态的,这看起来很奇怪。

无论如何,在多个库中使用全局变量时要小心,如果您有一个共享代码库(DLL),则每个部分都会获得一个值。请查看问题,可能会有用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接