包含常量成员的 POD 结构

2024-04-16

有了这个代码:

struct A
{
    int i;
    const int b;
};

// The union is to verify that A is a type that can be used in a union.
union U
{
    A a;
    int b;
};

int main()
{
    U a = {1, 1};
    U b = {2, 1};
}

g++ 版本 4.8.3 抱怨一个错误:

a.cpp:9:4: error: member ‘A U::a’ with copy assignment operator not allowed in union
  A a;
    ^
a.cpp:9:4: note: unrestricted unions only available with -std=c++11 or -std=gnu++11

但 clang 3.5.0 编译此代码没有错误。哪一个是正确的?这是编译器错误吗?

我尝试解决这个问题:

来自C++03标准第9.5节第1段:

在联合体中,任一时刻最多有一个数据成员处于活动状态,即任一时刻联合体中最多可以存储一个数据成员的值。 [注意:为了简化联合的使用,做了一个特殊的保证:如果一个 POD 联合包含多个共享公共初始序列 (9.2) 的 POD 结构,并且如果该 POD 联合类型的对象包含以下之一POD 结构体,允许检查任何 POD 结构体成员的公共初始序列;见 9.2。 ] 联合的大小足以包含其最大的数据成员。每个数据成员的分配就好像它是结构体的唯一成员一样。联合可以有成员函数(包括构造函数和析构函数),但不能有虚函数(10.3)。联合不得有基类。联合不得用作基类。具有非平凡构造函数(12.1)、非平凡复制构造函数(12.8)、非平凡析构函数(12.4)或非平凡复制赋值运算符(13.5.3、12.8)的类的对象不能是联合的成员,此类对象的数组也不能。如果联合包含静态数据成员或引用类型的成员,则程序格式错误。

来自C++03标准第12.8节第10和11段:

如果类定义没有显式声明复制赋值运算符,则隐式声明一个。类 X 的隐式声明的复制赋值运算符将具有以下形式X& X::operator=(const X&)如果 X 的每个直接基类 B 都有一个复制赋值运算符,其参数类型为 const B&、const volatile B& 或 B,并且对于 X 的类类型 M(或其数组)的所有非静态数据成员,每个此类类型有一个复制赋值运算符,其参数类型为 const M&、const volatile M& 或 M。

Otherwise, the implicitly declared copy assignment operator will have the form X& X::operator=(X&) ...

如果类 X 是隐式声明的,并且类 X 没有虚函数 (10.3) 和虚基类 (10.1),并且 X 的每个直接基类都有一个简单的复制赋值运算符,则类 X 的复制赋值运算符是简单的,并且对于X 的所有非静态数据成员都是类类型(或其数组),每个这样的类类型都有一个简单的复制赋值运算符;否则复制赋值运算符是不平凡的。

我不确定哪个编译器是正确的,因为我不知道常量成员是否有一个简单的复制赋值运算符。

Edit:编译命令为:

clang++ a.cpp -o a
g++ a.cpp -o a

Edit2:为了表明 g++ 没有抱怨 A::bconst但 A 没有构造函数,我也尝试了这个程序:

struct A
{
    int i;
    const int b;
};

int main()
{
    A a = {1, 1};
}

在 g++ 和 clang++ 上编译都没有错误:

g++ b.cpp -o b
clang++ b.cpp -o b

正如您正确指出的那样,复制赋值运算符是隐式的declared和琐碎的。 默认构造函数也是如此,它也很简单并且是隐式声明的。

请注意,这两个成员函数都不是隐式的defined- 只有在使用它们时才会发生,[class.ctor]/7:

类的隐式声明的默认构造函数是隐含地 定义的当它用于创建其类类型(1.8)的对象时。

..这里显然不是这种情况。
这是关键的区别,也是 @dasblinkenlight 的引用与此事无关的原因:默认构造函数从未定义,因此缺少段落内存初始化器 IDs 不适用。

How are const那么成员和赋值运算符连接起来了吗?这里:

隐式声明的复制赋值运算符是隐式定义的 当为其类类型的对象分配其类类型的值或从其类类型派生的类类型的值时。如果一个程序的副本分配的类是不正确的 运算符是隐式的defined has:

  • 的非静态数据成员const type, 或者 [..]

因此,如果使用复制赋值运算符,程序将是格式错误的。但事实并非如此。所有特殊成员函数都是单独声明的,并且对const非静态数据成员的性质仅适用于隐式定义的特殊成员函数。

举个例子,以

struct A
{
    int i;
    const int b;
};

int main()
{
    A a = {1, 1};
}

Which 在 GCC 下编译良好 http://coliru.stacked-crooked.com/a/51e646785c251020。您的程序也应该是格式良好的,因为对工会成员特殊成员函数的琐碎性的所有要求都满足A.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

包含常量成员的 POD 结构 的相关文章

随机推荐