简体   繁体   English

Linux gcc和Windows Visual Studio处理静态常量之间的区别?

[英]Difference between Linux gcc and Windows Visual Studio handling of static constants?

We have been compiling a library on both Linux (gcc) and Windows (Visual Studio), and as expected, finding minor, but not significant differences between what it takes to get a clean compile on both platforms. 我们一直在Linux(gcc)和Windows(Visual Studio)上编译一个库,并且正如预期的那样,在这两个平台上进行干净编译所需的内容之间没有细微但不显着的差异。

Today, I changed gcc compiler flag to use -fPIC (to enable making a shared library). 今天,我将gcc编译器标志更改为使用-fPIC (以启用创建共享库)。 When we tested linking a program against the library, we started getting errors (for the first time), with undefined reference to 2 static constants which are declared and initialized in the header file (but not in .cpp file). 当我们测试将程序链接到库时,我们开始出现错误(第一次),它带有undefined reference对2个静态常量的undefined reference ,这些常量在头文件(而不是.cpp文件)中声明和初始化。

I found this StackOverflow answer which seemed to address the problem, explaining that, even if static const is initialized in header file, it still needs to be defined in the code file. 我发现了这个StackOverflow答案 ,似乎可以解决该问题,并解释说,即使在头文件中初始化了static const ,它仍然需要在代码文件中进行定义。 And making that change did remove the gcc linker error. 进行该更改确实消除了gcc链接器错误。

Visual Studio, however, didn't like that change, and generated multiple definition errors. 但是,Visual Studio不喜欢这种更改,并生成了multiple definition错误。 We had to wrap the definition needed a preprocessor conditional to get Visual Studio to compile cleanly. 我们必须包装一个需要预处理程序的定义,以使Visual Studio能够干净地编译。

Can someone enlighten me as to what the difference is here? 有人可以启发我这有什么区别吗? (Code excerpt is below.) (代码摘录如下。)

msg.h 消息

class msg
{
  public:
    static const int EMPTY_INT_VALUE = INT_MAX;
    static const char EMPTY_STRING_VALUE = '\002';
    // can't define value in header, defined in cpp file
    static const double EMPTY_DOUBLE_VALUE;   
    ...
}

msg.cpp msg.cpp

#include "msg.h"

const double msg::EMPTY_DOUBLE_VALUE(DBL_MAX);

#ifndef _WIN32
// g++ requires these definitions, vs 2010 doesn't like them
const int msg::EMPTY_INT_VALUE;
const char msg::EMPTY_STRING_VALUE;
#endif

I've tracked it down to section 9.4.2 "Static data members" of the C++ language specification ( INCITS/ISO/IEC 14882-2011[2012] ): 我已经将其追溯到C ++语言规范( INCITS / ISO / IEC 14882-2011 [2012] )的第9.4.2节“静态数据成员”:

If a non-volatile const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression (5.19). 如果非易失性const static数据成员为整数或枚举类型,则其在类定义中的声明可以指定大括号或相等初始化器 ,其中每个作为赋值表达式的 初始化子句都是一个常量表达式(5.19 )。 A static data member of literal type can be declared in the class definition with the constexpr specifier; 可以使用constexpr说明符在类定义中声明文字类型的static数据成员; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. 如果是这样,则其声明应指定一个花括号或相等的初始化程序 ,其中每个作为赋值表达式的 初始化程序子句都是一个常量表达式。 [ Note: In both these cases, the member may appear in constant expressions. [ 注意:在这两种情况下,成员都可能出现在常量表达式中。 —end note ] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not contain an initializer . — [end note ]如果在程序中使用了成员(3.2),则该成员仍应在名称空间范围中定义,并且该名称空间范围定义不应包含初始化程序

So, for integral types (eg int and char in your example), you can initialize in the class definition. 因此,对于整数类型(例如您的示例中的intchar ),您可以在类定义中进行初始化。 If you do so, you must also define it at namespace scope (ie in your .cpp file) and without an initializer. 如果这样做,则还必须在名称空间范围(即, .cpp文件中)且没有初始化程序的情况下对其进行定义。 Elsewhere in that section of the spec it is stated that declaration of a static data member in its class is not a definition and must , therefore, be accompanied by a definition at namespace scope, which is what you're doing in your example. 在规范的该部分的其他地方,声明了在其类中声明static数据成员不是定义,因此必须在命名空间范围内随附定义,这是您在示例中所做的事情。

GCC follows this part of the specification, Visual C++ doesn't. GCC遵循规范的这一部分,而Visual C ++则不遵循。 I tested with Visual Studio 2012. 我使用Visual Studio 2012进行了测试。

Here's another discussion of Visual C++'s noncompliance in this regard. 这是关于Visual C ++在这方面的不合规性的另一讨论。 The workaround described here is exactly what you're doing: guard the definition of the integral variables, although they're using _MSC_VER . 此处描述的解决方法正是您要执行的操作:保护整数变量的定义,尽管它们使用的是_MSC_VER

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Linux下Visual Studio和gcc之间的C ++兼容性 - C++ compatibility between Visual Studio and gcc under Linux Visual Studio和GCC之间的const引用语法差异 - const reference syntax difference between visual studio and gcc Visual Studio 2010和gcc / g ++ 4.6.3之间iostream行为的意外差异 - Unexpected difference in iostream behavior between visual studio 2010 and gcc/g++ 4.6.3 如何在Windows或Linux,32或64位,Visual Studio或g ++上的静态或动态版本下编译Qt 5 - How to compile Qt 5 under Windows or Linux, 32 or 64 bit, static or dynamic on Visual Studio or g++ 无法在 clang Linux 中分配非静态成员 function,但我可以在 Visual Studio ZAEA23489CE3AA9B4EZCD?EBA - Cannot assign a non-static member function in clang Linux, but I can in Visual Studio Windows? 适用于Windows和Linux的Visual Studio 2010项目 - Visual studio 2010 project for windows and linux 将 Windows 解决方案移植到 Visual Studio 中的 Linux - Porting Windows Solution to Linux in visual studio 如何在Visual Studio C ++中实现Windows和linux之间可移植的串行端口编程? - How to do serial port programming in visual studio C++ that portable between Windows & linux? Windows 和 Linux 中 USB 串口的区别 - Difference between USB Serial in Windows and Linux Visual Studio中/ GL和/ LTCG之间有什么区别 - What is the difference between /GL and /LTCG in Visual Studio
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM