【问题标题】:Global variables and scope - C++全局变量和范围 - C++
【发布时间】:2010-10-07 08:46:04
【问题描述】:

我在制作全局变量时遇到了小问题。我正在使用 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;

谢谢

【问题讨论】:

  • 显示所有代码。这应该像你描述的那样有效,所以肯定有其他问题。
  • 你提到的那个库,它是一个单独的DLL吗?它是静态链接的 DLL 吗?还是您使用LoadLibrary() 加载它?可能是延迟加载?
  • 它是一个静态库。我已经在测试项目的项目依赖项中设置了。
  • 我支持 Pax -- 既然您已经展示了代码,我相信这应该可以正常工作。可能是一些不相关的问题,例如您正在链接旧版本的库? (例如,您忘记重新构建库的发布版本。)这两个模块也是使用 相同 设置构建的吗?
  • 等一下——你的库中的“字符串文本”也是一个全局变量吗?如果是这样,那么您遇到了“静态初始化顺序惨败”,这是 C++ 的一个已知问题。请参阅马特的答案以获取解决方案。

标签: c++ variables global-variables scope


【解决方案1】:

不要使用全局变量。只是不要。更好的是,如果您必须拥有全局可访问的数据,则使用将返回 globalWord 的全局函数,如下所示:

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

这使您免于初始化顺序问题(请阅读 Effective C++ item #4)。

【讨论】:

  • 谢谢。那么字符串单词将有一个生命周期直到程序结束?我也需要设置值。那么我可以有一个 SetGlobalWord 方法吗?如果是,我在哪里设置值,我的意思是哪个变量?
  • Matt,例如,如何将此变量更改为“Bye Dad”?
  • @Matt:将返回值更改为引用后立即+1。 Appu 特别需要能够更改值。
  • 另外请注意,目前,在除 g++ 之外的大多数 C++ 编译器上,如果您需要从多个线程访问 globalWord(),您需要使用平台提供的任何互斥原语来保护 word 的定义。
  • @j_random_hacker,G++ 从什么时候开始自动执行此操作的?即使使用全局变量,线程问题也仍然存在。 (毕竟,函数静态只是作用域的全局变量。)
【解决方案2】:

使用“extern”关键字,您是在告诉编译器实际变量存在于其他地方。您还应该在一个只有一个的地方创建一个没有外部变量的同名变量。通常,如果定义其中两个,链接器会出错,但如果一个在库中,一个不在库中,则可能无法识别。

编辑:确保 global.cpp 仅在库或测试程序中,而不是两者。

【讨论】:

    【解决方案3】:

    问题很可能是初始化顺序之一。程序链接时,有2个地方在初始化时使用了globalWord

    1. text("string text = globalWord;")的初始化中
    2. globalWord本身的初始化

    不幸的是,C++ 标准没有指定来自不同模块的全局变量的初始化顺序。类似于 Matt's answer 使用函数或简单类(例如单例)来访问全局值的方法是强制执行特定初始化顺序的常用方法。

    The C++ FAQ talks about this a little - 如果您打算在程序中修改globalWord,情况会比他们讨论的要复杂一些,因为他们似乎没有解决设置隐藏在“首次使用时构造”后面的值的问题功能。通常这样的事情需要something like a singleton class

    【讨论】:

    • 这如何解释调试器在不同的上下文中显示不同的内容?
    • 好主意,但 Appu 刚刚回复了我的评论,说“文本”是在 main() 启动后初始化的局部变量,此时所有全局变量都已初始化(以某种顺序)。所以 AFAIK 静态初始化顺序惨败不是这里的问题。
    • @Mark- 你是对的 - 这个答案可能无法解释他所描述的行为(尽管调试描述对我来说并不完全清楚)。我的答案基于代码 sn-ps - 希望它们是从实际代码中复制的(通过剪贴板)。
    【解决方案4】:

    当你有一个 DLL 时,你描述的那种行为似乎更像是一个问题,但你说你的库是静态的,这看起来很奇怪。

    无论如何,请注意多个库中的全局变量,如果您有一个共享代码库 (DLL),您将获得每个部分的值。查看this问题,可能有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-26
      • 1970-01-01
      • 1970-01-01
      • 2012-04-29
      • 2017-02-17
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      相关资源
      最近更新 更多