在C / C ++中初始化结构的const成员...依赖于编译器吗? [英] Initializing const members of structs in C/C++... compiler dependent?

查看:85
本文介绍了在C / C ++中初始化结构的const成员...依赖于编译器吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,我在使用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:


  1. 为什么编译器中存在方差?在这一点上,标准是否模棱两可?

  2. 任何解决方法?鉴于我卡在编译器版本和头文件中,所以看不到任何内容。

谢谢!

推荐答案

标准很明确。拥有 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆