对静态变量的更改超出范围?(C++)
changes to static variable goes out of scope? (C++)
我有一个包含静态变量的头文件,例如窗口宽度和高度。
我通过 XML 文件读取这些变量的新值,但是一旦更改了这些更改的函数超出范围,这些更改似乎就不会被注册。
举例说明:
// These are in a separate header file
static int width = 0;
static int height = 0;
aClass::Init()
{
width = readFromXMLFile(); // returning 800
height = readFromXMLFile(); // returning 600
// Here width and height are 800/600
}
aClass::Run()
{
...
}
Main
{
Init()
// Here, width and height are 0/0 again
Run()
}
等一下...你有
static int height = 0;
static int width = 0;
在头文件中? 这将在包含标头的每个编译单元中创建文件范围的static
。 如果要使用全局变量,请在标头中将它们声明为 extern
,并在一个编译单元中定义它们。
如果你没有在某处将静态声明为 extern,你最终得到的实际上是每个编译单元的多个静态副本(同名)。
正确的示例:
测试.h
extern int mystatic;
测试.cpp
int mystatic = 0;
void myFunction() // or member funciton, who cares
{
mystatic = 42;
}
主.cpp
#include "test.h"
int main()
{
std::cout << mystatic << std::endl; // prints 0
//
myFunction(); // or use classes and trigger the same
//
std::cout << mystatic << std::endl; // prints 42
return 0;
}
呵呵
你应该在头文件中声明静态变量,extern
ed并在 cpp 文件中定义它们。
.h 文件:
extern int foo;
.cpp某处的文件:
int foo;
您误解了关键字static
.在C++这个关键字有很多含义,都是松散相关的。
在顶层,而不是在类、结构或函数定义中,关键字 static
创建一种奇怪的全局变量。该全局变量仅在它出现的"编译单元"中可见。"编译单元"的想法是通过C++预处理器的工作方式创建的。
所有以#
开头的东西都不是C++语言的一部分,而是预处理器的一部分。预处理器读取所有这些指令并将编译单元拼凑在一起。它扩展所有宏,并将所有#include
指令替换为指令中提到的文件内容。
使用 gcc,您可以通过将 -E
选项传递给编译器来查看此结果。这将在编译C++文件时显示生成的"编译单元"的内容。
您会注意到,所有#include
ed 头文件都成为编译单元的一部分。
现在,转到文件级静态变量...
这些变量是编译单元的局部变量。如果在另一个编译单元中声明具有相同名称的文件级静态变量,则它们将是不同的变量。如果更改一个编译单元中的值,则它们与其他编译单元中的这些变量的值无关。
还记得头文件最终是如何被复制到每个编译单元中的吗?
这意味着在头文件中声明的文件级静态变量最终在每个编译单元中都有副本。它们看似是全球性的,但实际上会有许多非交互的副本。
在您的情况下,您可以通过使它们完全全局化来轻松解决此问题。您可以使用头文件中的 extern
关键字执行此操作。这基本上使编译器注意到存在具有该名称的全局变量。然后,在一个特定的编译单元中将它们声明为非外部。然后,在编译该编译单元产生的.o
文件中为变量提供空间。所以基本上:
在foo.h
:
extern int width;
extern int height;
在some_random.cpp
(但可能是foo.cpp
):
#include "foo.h"
int width = 0;
int height = 0;
编译单元的概念仅与文件级(不在类、结构或函数定义内部)静态变量相关。在类、结构或函数定义中声明的静态变量遵循一些不同的规则。不知何故,一旦您了解了static
的每个不同规则,它们都被称为 static
真的很有意义。:-)
- 为什么在全局范围内使用"extern int a"似乎不行?
- 尝试通过多个向量访问变量时,向量下标超出范围
- 错误:未在此范围内声明'reverse'
- 正在将指针转换为范围
- 使用std::transform将一个范围的元素添加到另一个范围中
- 在基于范围的for循环中使用结构化绑定声明
- 如何计算数据类型的范围,例如int
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- 在C++中查找范围的长度
- 如何设置一个范围来提取我想要获得的信息
- 并行用于C++17中数组索引范围内的循环
- 为左值和右值的包装器实现C++范围
- 求出有多少个数字是完美平方,而sqrt()是L,R范围内的素数
- 关于:C++中异常对象的范围:为什么我没有得到副本?
- 超出范围时使用对象
- 不计算一个范围内的完美数
- ";结果类型必须是可从输入范围的值类型""构造的;创建std::vector时
- 基于范围的 for 循环:迭代使用一个元素扩展的向量
- 如何访问超出其块范围的对象?
- 矢量下标超出SFML游戏中的范围