C++ 应用程序中全局变量的使用
Use of global variables in C++ application
我使用全局变量没有任何明显的问题,但想知道我使用全局变量是否存在潜在问题或缺点。
在第一种情况下,我将 const globals 包含到一个 globals.h 文件中,然后我将 header 包含到我需要访问任何一个全局变量的各种实现文件中:
globals.h
const int MAX_URL_LEN = 100;
const int MAX_EMAIL_LEN = 50;
…
在第二种情况下,我在应用程序执行时在实现文件中声明并初始化全局变量。这些全局变量再也不会被修改。当我需要从不同的实现文件访问这些全局变量时,我使用 extern 关键字:
main.cpp
char application_path[128];
char data_path[128];
// assign data to globals
strcpy(application_path, get_dll_path().c_str());
…
do_something.cpp
extern char application _path[]; // global is now accessible in do_something.cpp
关于上面的第一个场景,我考虑过删除所有不同的“include globals.h”,并在需要访问这些全局变量的地方使用 extern 但没有这样做,因为只包含 globals.h 太方便了。
我担心每个包含 globals.h 的实现文件都会有不同版本的变量。
我是否应该在需要访问的任何地方使用 extern 而不是包含 globals.h?
请指教,谢谢
您的实施目前没有问题。
时全局变量成为问题
- 您的程序在增长,全局变量的数量也在增长。
- 不知道你在想什么的新人加入团队。
当您的程序变成多线程时,数字 1 变得特别麻烦。然后你有许多线程使用相同的数据,你可能需要保护,这对于一个全局列表来说很困难。
通过根据一些标准(例如目的或主题)将数据分组到单独的文件中,您的代码随着代码的增长变得更易于维护,并且您为项目的新程序员留下面包屑以了解软件的工作原理。
全局变量的一个问题是,当您在代码中包含第 3 方库时,有时它们会使用与您的同名的全局变量。确实有些时候全局是有意义的,但如果可能的话,您还应该注意做一些事情,比如将它放入命名空间中。
全局可变变量
- 在所有代码中提供无形的影响线,并且
- 您不能依赖它们的值,也不能依赖它们是否已初始化。
也就是说,全局可变变量对数据流的作用就像全局 goto
曾经对执行流所做的那样,造成一团糟,浪费了大家的时间。
常量全局变量更好,但即使对于那些你 运行
- 初始化顺序失败。
我记得当我意识到我在包装一个众所周知的 GUI 框架时遇到的所有麻烦都是由于它不必要地使用全局变量并引发初始化顺序失败时我是多么生气。首先,愤怒是针对作者的,然后是我自己太愚蠢了,没有意识到发生了什么(或者更确切地说,没有发生)。不管怎样
所有这一切的明智解决方案是迈耶斯的单例,例如
inline
auto pi_decimal_digits()
-> const string&
{
static const string the_value = compute_pi_digits();
return the_value;
}
对于从某个知道值的地方动态初始化的全局变量的情况,“一个程序员的常量是另一个程序员的变量”,没有好的解决方案,但是一个实际的解决方案是接受 运行 时间错误的可能性并至少检测到它:
namespace detail {
inline
auto mutable_pi_digits()
-> string&
{
static string the_value;
return the_value;
}
} // namespace detail
inline
void set_pi_digits( const string& value )
{
string& digits = detail::mutable_pi_digits();
assert( digits.length() == 0 );
digits = value;
}
inline
auto pi_digits()
-> const string&
{ return detail::mutable_pi_digits(); }
我使用全局变量没有任何明显的问题,但想知道我使用全局变量是否存在潜在问题或缺点。
在第一种情况下,我将 const globals 包含到一个 globals.h 文件中,然后我将 header 包含到我需要访问任何一个全局变量的各种实现文件中:
globals.h
const int MAX_URL_LEN = 100;
const int MAX_EMAIL_LEN = 50;
…
在第二种情况下,我在应用程序执行时在实现文件中声明并初始化全局变量。这些全局变量再也不会被修改。当我需要从不同的实现文件访问这些全局变量时,我使用 extern 关键字:
main.cpp
char application_path[128];
char data_path[128];
// assign data to globals
strcpy(application_path, get_dll_path().c_str());
…
do_something.cpp
extern char application _path[]; // global is now accessible in do_something.cpp
关于上面的第一个场景,我考虑过删除所有不同的“include globals.h”,并在需要访问这些全局变量的地方使用 extern 但没有这样做,因为只包含 globals.h 太方便了。
我担心每个包含 globals.h 的实现文件都会有不同版本的变量。
我是否应该在需要访问的任何地方使用 extern 而不是包含 globals.h?
请指教,谢谢
您的实施目前没有问题。
时全局变量成为问题- 您的程序在增长,全局变量的数量也在增长。
- 不知道你在想什么的新人加入团队。
当您的程序变成多线程时,数字 1 变得特别麻烦。然后你有许多线程使用相同的数据,你可能需要保护,这对于一个全局列表来说很困难。 通过根据一些标准(例如目的或主题)将数据分组到单独的文件中,您的代码随着代码的增长变得更易于维护,并且您为项目的新程序员留下面包屑以了解软件的工作原理。
全局变量的一个问题是,当您在代码中包含第 3 方库时,有时它们会使用与您的同名的全局变量。确实有些时候全局是有意义的,但如果可能的话,您还应该注意做一些事情,比如将它放入命名空间中。
全局可变变量
- 在所有代码中提供无形的影响线,并且
- 您不能依赖它们的值,也不能依赖它们是否已初始化。
也就是说,全局可变变量对数据流的作用就像全局 goto
曾经对执行流所做的那样,造成一团糟,浪费了大家的时间。
常量全局变量更好,但即使对于那些你 运行
- 初始化顺序失败。
我记得当我意识到我在包装一个众所周知的 GUI 框架时遇到的所有麻烦都是由于它不必要地使用全局变量并引发初始化顺序失败时我是多么生气。首先,愤怒是针对作者的,然后是我自己太愚蠢了,没有意识到发生了什么(或者更确切地说,没有发生)。不管怎样
所有这一切的明智解决方案是迈耶斯的单例,例如
inline
auto pi_decimal_digits()
-> const string&
{
static const string the_value = compute_pi_digits();
return the_value;
}
对于从某个知道值的地方动态初始化的全局变量的情况,“一个程序员的常量是另一个程序员的变量”,没有好的解决方案,但是一个实际的解决方案是接受 运行 时间错误的可能性并至少检测到它:
namespace detail {
inline
auto mutable_pi_digits()
-> string&
{
static string the_value;
return the_value;
}
} // namespace detail
inline
void set_pi_digits( const string& value )
{
string& digits = detail::mutable_pi_digits();
assert( digits.length() == 0 );
digits = value;
}
inline
auto pi_digits()
-> const string&
{ return detail::mutable_pi_digits(); }