当全局变量在头文件中声明为静态时,没有链接器错误
No linker error when global variable declared static in the header file
可能重复:
C++中的静态变量
// x.h
int i = 3;
// x1.cpp
#include"x.h"
//...
// x2.cpp
#include"x.h"
//...
上面的代码将给出链接器错误。然而,如果我声明,
//x.h
static int i = 3;
它不会在gcc中给出链接器错误,即使我们有相同的#include
!我们是否为每个.cpp
文件创建不同的static int i;
?它会导致任何静默链接错误(由于相同的名称(吗?
编译C代码时,它一次是一个"翻译单元"。早期,#includes被扩展到引用文件的文本中。因此,在静态情况下,你得到的相当于x1.cpp说static int i = 3;
和x2.cpp做同样的事情。static
在这里的意思大致是"不要与其他翻译单位共享这个。">
是的,当你使用static
时,你会产生两个不同的i
变量,它们彼此无关。这不会导致链接错误。
int x;
是实体x
的定义。C++的一个定义规则说,任何使用的变量都应该在程序中定义一次。因此出现了错误。
static
认为x
具有内在联系。也就是说,出现在one.cpp
和two.cpp
中的x是两个不同的不相关实体。
C++标准表示,在这种情况下不赞成使用static(根据Steve的评论,在C++0x中,这是不赞成的(。匿名命名空间提供了一种优越的替代方案。
namespace
{
int x;
}
还要注意,与C不同,在C++中,标量类型的常量变量也有内部链接。那是
const int x = 7; // won't give you an error if included in different source files.
HTH
我们是否在创建不同的静态int i;对于每个.cpp文件?
是
它会导致任何静默链接错误(由于相同的名称(吗?
没有。由于静态,它们有不同的名称。
如果这不是您想要的行为,则需要在头文件中使用extern
,并在一个转换单元(.cpp
文件(中分配变量
static
创建一个仅在单元内部可见的全局变量。
如果您想在多个计算单元中使用一个变量,请在标头中使用extern
,并在不使用extern
的实现中声明它。
您在第一个代码示例中得到链接器错误,因为i是在两个编译单元中定义和导出的。在第二种情况下,i是静态的,因此没有导出的符号,因为静态变量只在当前编译单元中可见,不会导出到链接器。在这种情况下,您有两个自变量,它们都被称为i.
在编写时,代码看起来像是多个.cpp文件正在访问同一个i
,而实际上,每个.cpp文件都有自己的副本。这可能会导致误解和错误。
如果您只想有一个i
的副本,首选的习惯用法是将其包装在x.h
:中的访问器函数中
int& GetI() {
static int i = 3; // this initialization only happens once.
return i;
}
如果确实希望为每个.cpp文件分别声明i
的副本,则更清晰的表达方式是在每个.cpp中单独声明i
:
namespace {
int i;
}
为了安全起见,如上所述将它放在匿名命名空间中可以防止从其他.cpp文件访问它。
- 静态数据成员的问题-修复链接错误会导致编译器错误
- Visual Studio mkl_link_tool.exe链接错误
- C++ 实现模板单例类时出现链接错误
- 使用类模板的方法链接错误
- MySQL C++连接器链接错误
- VS 2015 链接错误 无法构建依赖于 libcurl 的项目
- 运行 C++ 单元测试时LNK2005链接错误
- 对 CMake 中'cudaRegisterLinkedBinary'链接错误的未定义引用?
- 链接错误,包括我创建的相同头文件 - C++
- 在Embarcadero C++ Builder中生成的DLL未解决的外部链接错误
- 使用标头保护的多个定义链接错误
- 链接错误:未定义对 stdscr 和 wgetch 的引用
- 使用 Vivek 的 Vcam / 捕获源过滤器构建/链接错误
- 升压program_options中的链接错误
- 使用 g++ 预处理器进行替换会导致链接错误
- 在调试配置中编译工作正常,但发布会给出链接错误
- 相邻矩阵设置链接错误
- 包含常量变量并包含在多个文件中的标头的链接错误
- C++链接错误,我理解但无法解决
- 是什么导致macOS Mojave上的GoogleTest链接错误