在C / C ++中初始化结构的const成员...依赖于编译器吗? [英] Initializing const members of structs in C/C++... compiler dependent?
问题描述
最近,我在使用Borland C ++ 5.2的旧版环境中遇到编译器错误。我有一个.cpp文件,其中包含一些我无法控制的C源头。标头包含一个包含const成员的结构定义,并且编译器抱怨类中没有构造函数的常量成员。经调查,此错误似乎与编译器有关。以下是一些示例代码,其中包含来自各种编译器的结果:
Recently I ran into a compiler error in a legacy environment using Borland C++ 5.2. I had a .cpp file which included a header from some C source which I don't control. The header contained a struct definition which included const members, and the compiler complained about a "constant member in class without constructors". On investigation, this error seems to be compiler-dependent. Here's some sample code w/ results from various compilers:
#include <stdio.h>
typedef struct {
const float a;
} _floater;
int main()
{
_floater f = {5.1F};
printf("%f\r\n",f.a);
return 0;
}
Borland 5.2
E:\Projects\Scratchpad>bcc32 -P const_float.c
Borland C++ 5.2 for Win32 Copyright (c) 1993, 1997 Borland International
const_float.c:
Error const_float.c 13: Constant member ' ::a' in class without constructors
*** 1 errors in Compile ***
Microsoft VS 2003 .NET:
E:\Projects\Scratchpad>cl /TP const_float.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
const_float.c
const_float.c(19) : error C2552: 'f' : non-aggregates cannot be initialized with
initializer list
Microsoft VS 2008:
C:\Projects\Scratchpad>cl /TP const_float.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
const_float.c
Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.
/out:const_float.exe
const_float.obj
C:\Projects\Scratchpad>const_float.exe
5.100000
G ++ 3.3.3
$ g++ const_float.c -o const_float.exe
const_float.c:25:2: warning: no newline at end of file
$ ./const_float.exe
5.100000
请注意Borland在声明时失败的结构,因为它有一个const成员,但没有构造函数,而VS 2003可以使用声明,但是在尝试使用初始化列表实例化它时会抱怨–考虑到该结构是非聚合类型。 VS2008和g ++非常高兴。
[抱歉,我刚刚意识到错误中的行#是错误的,因为我在发布之前删除了一些注释掉的行。]
Note that Borland fails at the declaration of the struct, because it has a const member but no constructors, while VS 2003 is ok w/ the declaration, but complains when you try to instantiate it with an initializer list – considering the struct a non-aggregate type. VS2008 and g++ are perfectly happy. [Apologies.. I just realized that the line #s in the errors are wrong because I stripped some commented-out lines before posting.]
Microsoft的定义的集合在这里: http://msdn.microsoft.com/en-us/ library / 0s6730bb.aspx 。在我看来,const成员不会使结构成为非聚合,但也许他们早在2003年就完成了。
Microsoft’s definition of aggregates is here: http://msdn.microsoft.com/en-us/library/0s6730bb.aspx. It’s not apparent to me that const members would make a struct non-aggregate, but maybe they did back in 2003.
看来,最新的Borland(Embarcadero)编译器将此视为警告而非错误: http ://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devwin32/wrnmembnocons_xml.html 。
It also appears that the latest Borland (Embarcadero) compiler treats this as a warning rather than an error: http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devwin32/wrnmembnocons_xml.html .
因此,有2个问题我猜:
So, 2 questions I guess:
- 为什么编译器中存在方差?在这一点上,标准是否模棱两可?
- 任何解决方法?鉴于我卡在编译器版本和头文件中,所以看不到任何内容。
谢谢!
推荐答案
标准很明确。拥有 const
成员不会阻止类成为聚合。
The standard is pretty clear. Having a const
member doesn't bar a class from being an aggregate.
8.5.1 [dcl.init .aggr]
8.5.1 [dcl.init.aggr]
aggregate 是没有用户声明的构造函数的数组或类(第9节) (12.1),没有私有或受保护的非静态数据成员(第11条),没有基类(第10条)和虚拟函数(10.3)。
An aggregate is an array or a class (clause 9) with no user-declared constructors (12.1), no private or protected non-static data members (clause 11), no base classes (clause 10), and no virtual functions (10.3).
复制初始化一个 const
对象是合法的,这是对成员的聚合初始化执行的初始化总计。在12.6.2的 mem-initializer-list 中没有命名没有用户声明的构造函数的 const
对象的限制仅适用于初始化
It is legal to copy-intialize a const
object and this is the initialization that aggregate initialization performs on the members of the aggregate. The restrictions on not naming a const
object with no user-declared constructor in the mem-initializer-list in 12.6.2 apply only to initialization by a constructor which doesn't apply because aggregate initialization happens instead.
关于较早的编译器失败的原因,我不知道。我只能说他们在这方面不符合标准。
As to why the older compilers fail, I don't know. I can only say that they don't conform to the standard in this respect.
这篇关于在C / C ++中初始化结构的const成员...依赖于编译器吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!