Visual Studio 2010 c++完全支持类内const变量吗?
Does Visual Studio 2010 C++ Fully Support in-Class const Variables?
这个问题与之前问过的一个问题密切相关。
为了使Visual Studio 2010 c++调试器能够解析类内初始化的const变量,必须为该变量提供一个全局定义。
。
下面是类定义:
class B{
public:
static const int m_b=100;
};
成员的全局作用域定义:
const int B::m_b;
如果没有全局定义,代码可以工作,但调试器无法在B的方法中看到m_b。
然而,这导致了另一个问题。在重要的头文件包含安排(完整代码如下所示)中,Visual Studio会产生以下链接错误:
error LNK2005: "public: static int const B::m_b" (?m_b@B@@2HB) already defined in a.obj
1>a.exe : fatal error LNK1169: one or more multiply defined symbols found
但是GCC会成功编译、链接并运行代码。
下面是问题代码:
文件a.cpp:
#include <iostream>
#include "a.h"
const int B::m_b;
int main()
{
B b;
std::cout << b.m_b;
return 0;
}
文件a.h:
#pragma once
#include "b.h"
文件b.cpp:
#include "b.h"
文件b.h:
#pragma once
class B {
public:
static const int m_b = 100;
};
以下是链接器选项(默认的VS10控制台程序):
/OUT:"a.exe"
/NOLOGO "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib"
/MANIFEST
/ManifestFile:"Debuga.exe.intermediate.manifest"
/ALLOWISOLATION
/MANIFESTUAC:"level='asInvoker' uiAccess='false'"
/DEBUG
/PDB:"Debuga.pdb"
/PGD:"Debuga.pgd"
/TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE
以下是编译器选项(默认VS10控制台程序):
/ZI /nologo /W3 /WX- /Od /Oy- /D "_MBCS" /Gm /EHsc /RTC1 /GS /fp:precise /Zc:wchar_t
/Zc:forScope /Fp"Debugsndbx.pch" /Fa"Debug" /Fo"Debug" /Fd"Debugvc100.pdb" /Gd
/analyze- /errorReport:queue
同样,它使用GCC (g++ a.p pp b.p)构建、链接并成功运行。我提供的代码是完整的,因此可以复制、粘贴和运行。
你不应该把数据的非模板定义放在头文件中,因为你会在链接时得到多个定义错误。无论变量是成员变量、静态成员变量还是const静态成员变量都不会改变这一点。
将定义放在一个编译单元中,就像处理任何其他单例一样。
这实际上看起来像一个Visual c++ bug。如果您显示完整的错误消息,即
,将会有很大帮助。b。obj:错误LNK2005: "public: static int B::m_b" (?m_b@B@@2HB)已经在a.obj中定义.exe:致命错误LNK1169:发现一个或多个乘法定义符号
如果编译器工作正常,该符号不会在b.b obj中的任何地方定义。
此外,尝试使用__declspec(selectany)
告诉我们编译器知道这不是定义:
r:16404173b.h(3):错误C2496: 'B::m_b': 'selectany'只能应用于带有外部链接的数据项
最后,Visual c++清楚地定义了符号(不正确):
R:16404173>dumpbin/symbols b.objMicrosoft (R) COFF/PE dump版本10.00.40219.01微软公司版权所有。版权所有
Dump of file b.obj File Type: COFF OBJECT COFF SYMBOL TABLE 000 00AB9D1B ABS notype Static | @comp.id 001 00000000 SECT1 notype Static | .drectve Section length 2F, #relocs 0, #linenums 0, checksum 0 003 00000000 SECT2 notype Static | .debug$S Section length 64, #relocs 0, #linenums 0, checksum 0 005 00000000 SECT3 notype Static | .rdata Section length 4, #relocs 0, #linenums 0, checksum B4446054, selection 2 (pick any) 007 00000000 SECT3 notype External | ?m_b@B@@2HB (public: static int const B::m_b)
此外,我们看到它已经被标记为selectany
。但是在编译单元中有实际的定义:
Section length 4, #relocs 0, #linenums 0, checksum B4446054 229 00000000 SECTB9 notype External | ?m_b@B@@2HB (public: static int const B::m_b)
没有(pick any)
标注。这是正确的,这是对变量的权威定义。
在b.obj
中出现变量是错误的。编译器通过使用selectany
注释使简单的情况(头文件中的初始化)工作,但是当提供了真正的定义时,这种粗糙的解决方案就崩溃了。
最后,在a.p中,在实际定义上添加__declspec(selectany)
,可以解决链接错误。但是我担心这个符号仍然会被链接器优化掉,并且在调试期间不可用。您可以暂时使用/OPT:NOREF
来避免这种情况(但它会使您的可执行文件膨胀,因此在发布之前再次关闭该选项)。
根据clang将接受的内容,静态const变量的初始化必须在定义中而不是在声明中进行。
因此在你的页眉中你需要这样写:
class B{
public:
static const int m_b;
};
然后在你的cpp中的定义应该是这样的:
const int B::m_b = 100;
- 在内存不足之前,我可以声明多少个 const 变量?
- 当设置为 const 变量时使用 nullptr
- 声明与 const 变量和成员函数相同的标识符
- const变量是否可以在具有默认值的参数中赋值(作为可选参数)
- 编译器在传递 const 变量时返回错误:模板参数不是常量表达式
- 在成员函数之间传递const变量为数组的索引
- 为什么静态常量字符 * const 变量在为左值时可绑定到右值引用参数
- C 编译器可以执行用于返回值的命名const变量的RVO
- 如何访问一系列const变量作为const数组
- C 错误C3892:您无法分配const变量
- 是否可以在C++中推迟 const 变量的初始化,例如 Java 的"blank final"功能?
- 为什么将FMTFLAG指定两次 - 作为枚举的一部分,而另一个实例为静态const变量
- 使用非const变量代替所需的const变量(C )
- 使用const变量时,非静态数据成员的使用无效
- 定义,初始化全局const变量是安全的吗?
- const vs non-const变量一旦分配就没有变化
- 为什么设置const变量(将以相同的值存储)会导致不同的结果
- CPP中的私有静态常规成员变量与const变量
- 在避免新分配的同时,const变量的复杂初始化
- 如何通过其地址更改const变量的值