关于静态变量的问题
Question about static variable
我读了很多关于静态变量的文档。这里有一个我不明白的例子。假设类中的静态变量是这样声明的:
class Something
{
public:
static int s_nValue;
};
int Something::s_nValue = 1;
int main()
{
Something::s_nValue = 2;
std::cout << Something::s_nValue;
return 0;
}
我的问题是:我们已经在类中声明了s_nvalue
,为什么需要重新定义它?如果我们之前不写int
,它会显示一个错误。为什么会这样呢?
在一个普通的c++程序中,你的类被定义在头文件中,所有使用它们的源文件都包含在头文件中。因此,如果它按照您期望的方式工作,那么每个源文件都将拥有该静态变量的自己的副本,而实际上它们应该共享一个副本。这违反了"单一定义规则"……每个对象只能定义为存在于一个地方。
因此,在类中声明变量只是向编译器宣布,在某个地方将有一个具有此名称和类型的变量;它不会指示编译器为它分配空间。此时,该变量在包含它的任何源文件中都保持未定义状态。然后,在一个特定的源文件(通常是那个特定类的实现文件)中,提供一个实际的定义,即int Something::s_nValue;
行。这要求编译器为变量分配空间,以便它只存在于一个位置,并且当您将所有目标文件链接在一起时不会产生歧义。
这是c++的特性,当你定义一些东西时,你必须指定它的确切类型,即使你之前有一个声明。对于所有变量和函数都是如此。
旁注:不要重新定义它,否则会导致编译错误。你只需要定义它
声明和定义是不一样的。有时你可以同时做这两件事,但无论哪种方式,你都需要声明和定义一些东西。
为什么?
好吧,因为标准这么说,但是为什么标准这么说呢?
它与编译和链接的工作方式有关。如果我有几个源文件,a.cpp
和b.cpp
和几个头文件,a.h
和b.h
,那么我想编译它们。通常,您单独编译所有源文件以获得a.o
和b.o
,然后在最后将它们链接在一起以获得最终程序。
假设我们有:
// a.h =========================
class A { static int n; };
// b.h =========================
class B { static int n; };
// a.cpp =======================
#include "a.h"
#include "b.h"
int foo() { return A::n + B::n; }
// b.cpp =======================
#include "a.h"
#include "b.h"
int bar() { return A::n - B::n; }
请记住,#include
实际上只是将其他文件粘贴到包含文件中。所以编译器在编译a.cpp
和b.cpp
时看到的是:
// a.cpp =======================
class A { static int n; };
class B { static int n; };
int foo() { return A::n + B::n; }
// b.cpp =======================
class A { static int n; };
class B { static int n; };
int bar() { return A::n - B::n; }
A::n
和B::n
应该放在哪个目标文件中?a.o
还是b.o
?它在a.cpp
和b.cpp
中都声明了,所以编译器不知道把它放在哪里。如果你把它放在两者中,那么你将定义它两次,编译器将不知道使用哪个(在这种情况下,链接器会给你一个'multiply defined symbol'错误)。
这就是为什么我们需要一个定义。定义告诉我们把它放在哪个目标文件中。
// a.cpp =======================
#include "a.h"
#include "b.h"
int A::n = 0; // A::n goes in a.o
int foo() { return A::n + B::n; }
// b.cpp =======================
#include "a.h"
#include "b.h"
int B::n = 0; // B::n goes in b.o
int bar() { return A::n - B::n; }
值得指出的是,您可以将两者都放在a.cpp
或b.cpp
中。没关系,只要定义一次就行。
欢迎来到美妙的c++世界:声明vs定义。在你发布的代码中,有一个声明和一个定义。声明为符号指定了名称和类型。定义赋予符号一个"值"。
class Something
{
public:
// declaration.
static int s_nValue;
};
// definition.
int Something::s_nValue = 1;
这个过程类似于功能原型:
// declaration.
void f ( int i );
// definition.
void f ( int i )
{
std::cout << i << std::endl;
// ...
}
更令人困惑的是,有些语句同时执行这两项操作。例如,如果您不声明函数,则定义也充当声明(这对于静态变量是不可能的,就像您发布的Something::s_nValue
案例一样)。
这与C中的情况类似,在头文件中可以这样做:
extern int Something_s_nValue;
你的源文件,你会做:
int Something_s_nValue;
第一部分是头文件中的声明,第二部分是源文件中的定义。
- 为"adjacent"变量赋值时出现问题
- C++理解计算字符变量的问题
- 在通知提升间处理条件变量时未按住锁会导致问题
- C++线程安全:如果只有一个线程可以写入非原子变量,但多个线程从中读取. 会遇到问题吗?
- 将十六进制值设置为用于填充的字符变量时出现问题
- 初学者问题:如何访问此变量?
- 关于仅正确使用二传手和变量的问题
- 为什么在分配给成员变量之前获取unique_ptr的返回是一个问题?
- C++ 多线程中的锁和条件变量问题
- C++grpc的一些变量问题
- 我如何加载多个脚本而没有变量问题
- 未初始化的变量问题C++
- C++和引脚工具 - IF语句非常奇怪的双变量问题
- 如何通过引用捕获异常来解决局部变量问题
- sscanf写入变量问题
- 影子变量问题Qt
- C++ 中的局部变量问题
- 跨平台条件变量问题
- Makefile变量问题,make想要创建"*.o"而不是foo.o bar.o等
- c++变量问题