- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
相关:How to initialize a non-POD member in Union
标准说
At most one non-static data member of a union may have a brace-or-equal-initializer.
但是
struct Point {
Point() {}
Point(int x, int y): x_(x), y_(y) {}
int x_, y_;
};
union U {
int z;
double w;
Point p = Point(1,2);
};
#include <iostream>
int main () {
U u;
std::cout << u.p.x_ << ":" << u.p.y_ << std::endl;
}
打印 4196960:0
而不是预期的 1:2
。
我认为这是一个编译器错误。是这样吗?
最佳答案
C++11 [class.ctor]/5 个状态:
A default constructor for a class
X
is a constructor of classX
that can be called without an argument. If there is no user-declared constructor for classX
, a constructor having no parameters is implicitly declared as defaulted (8.4). An implicitly-declared default constructor is aninline public
member of its class. A defaulted default constructor for classX
is defined as deleted if:
X
is a union-like class that has a variant member with a non-trivial default constructor,- any non-static data member with no brace-or-equal-initializer is of reference type,
- any non-variant non-static data member of const-qualified type (or array thereof) with no brace-or-equal-initializer does not have a user-provided default constructor,
X
is a union and all of its variant members are of const-qualified type (or array thereof),X
is a non-union class and all members of any anonymous union member are of const-qualified type (or array thereof),- any direct or virtual base class, or non-static data member with no brace-or-equal-initializer, has class type
M
(or array thereof) and eitherM
has no default constructor or overload resolution (13.3) as applied toM
’s default constructor results in an ambiguity or in a function that is deleted or inaccessible from the defaulted default constructor, or- any direct or virtual base class or non-static data member has a type with a destructor that is deleted or inaccessible from the defaulted default constructor.
A default constructor is trivial if it is not user-provided and if:
- its class has no virtual functions (10.3) and no virtual base classes (10.1), and
- no non-static data member of its class has a brace-or-equal-initializer, and
- all the direct base classes of its class have trivial default constructors, and
- for all the non-static data members of its class that are of class type (or array thereof), each such class has a trivial default constructor.
Otherwise, the default constructor is non-trivial.
由于 OP 中的结构 Point
有一个重要的默认构造函数,
Point() {}
包含 Point
类型成员的 union 的默认默认构造函数 应该根据第一个项目符号定义为删除:
X
is a union-like class that has a variant member with a non-trivial default constructor
导致 OP 中呈现的程序格式错误。
然而,根据 core working group issue 1623,如果 union 成员有 brace-or-equal-initializer,委员会似乎认为这是一个缺陷。 :
According to 12.1 [class.ctor] paragraph 5,
A defaulted default constructor for class X is defined as deleted if:
X
is a union-like class that has a variant member with a non-trivial default constructor,...
X
is a union and all of its variant members are of const-qualified type (or array thereof),
X
is a non-union class and all members of any anonymous union member are of const-qualified type (or array thereof),...
因为非静态数据成员初始化器的存在在道德上等同于 mem-initializer,所以应该修改这些规则,不要将生成的构造函数定义为当 union 成员具有一个非静态数据成员初始化器。 (注意 9.5 [class.union] 第 2-3 段和 7.1.6.1 [dcl.type.cv] 第 2 段中的非规范性引用,如果更改此限制,也需要更新。)
如果 union 的所有成员都具有 const 限定类型,则向 9.5 [class.union] 添加要求非静态数据成员初始化程序或用户提供的构造函数也会很有帮助。
在更一般的说明中,为什么仅仅因为成员具有非平凡的默认构造函数而将默认构造函数定义为已删除? union 本身不知道哪个成员是事件成员,并且默认构造不会初始化任何成员(假设没有 brace-or-equal-initializer)。由 union 的“所有者”来控制事件成员(如果有的话)的生命周期,并且需要用户提供的构造函数会强制使用没有意义的设计模式。同样,为什么仅仅因为一个成员有一个非平凡的析构函数就将默认析构函数定义为删除?如果它仅适用于 union 还具有用户提供的构造函数时,我会同意此限制。
Issue 1623 的状态为“drafting”,表明委员会认为该问题可能是一个缺陷 - 为什么要允许 union 成员使用 brace-or-equal-initializer? - 但尚未花时间确定决议的适当措辞。实际上,该段落在当前的 C++14 草案 N3936 ([class.ctor]/4) 中基本相同,只是“任何直接或虚拟基类或非静态数据成员”的措辞处处被替换为更简单的“任何可能构造的子对象”。
虽然两个编译器的行为并不严格符合,但我认为 Clang 的行为符合标准的精神。似乎 GCC 被删除的默认构造函数和 brace-or-equal-initializer 的组合弄糊涂了:
存在 brace-or-equal-initializer 和最大警告 GCC 4.8.2 根本不执行 union 初始化,even warns that the members are used uninitialized :
main.cpp: In function 'int main()':
main.cpp:17:39: warning: 'u.U::p.Point::y_' is used uninitialized in this function [-Wuninitialized]
std::cout << u.p.x_ << ":" << u.p.y_ << std::endl;
^
main.cpp:17:22: warning: 'u.U::p.Point::x_' is used uninitialized in this function [-Wuninitialized]
std::cout << u.p.x_ << ":" << u.p.y_ << std::endl;
^
GCC 应该要么符合标准并将程序诊断为格式错误,要么模仿 clang 的行为并从 brace-or-equal-initializer 生成适当的构造函数。
关于c++ - union 中的大括号或相等初始化器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23005241/
我是 Spring 新手,这就是我想要做的事情: 我正在使用一个基于 Maven 的库,它有自己的 Spring 上下文和 Autowiring 字段。 它的bean配置文件是src/test/res
我在我的测试脚本中有以下列表初始化: newSequenceCore=["ls", "ns", "*", "cm", "*", "ov", "ov", "ov", "ov", "kd"] (代表要在控
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Class construction with initial values 当我查看 http://en.
我得到了成员变量“objectCount”的限定错误。编译器还返回“ISO C++ 禁止非常量静态成员的类内初始化”。这是主类: #include #include "Tree.h" using n
我有如下所示的a.h class A { public: void doSomething()=0; }; 然后我有如下所示的b.h #include "a.h" class b: publi
我需要解析 Firebase DataSnapshot (一个 JSON 对象)转换成一个数据类,其属性包括 enum 和 list。所以我更喜欢通过传递 DataSnapshot 来手动解析它进入二
我使用 JQuery 一段时间了,我总是使用以下代码来初始化我的 javascript: $(document).ready( function() { // Initalisation logic
这里是 Objective-C 菜鸟。 为什么会这样: NSString *myString = [NSString alloc]; [myString initWithFormat:@"%f", s
我无法让核心数据支持的 NSArrayController 在我的代码中正常工作。下面是我的代码: pageArrayController = [[NSArrayController alloc] i
我对这一切都很陌生,并且无法将其安装到我的后端代码中。它去哪里?在我的页脚下面有我所有的 JS? 比如,这是什么意思: Popup initialization code should be exec
这可能是一个简单的问题,但是嘿,我是初学者。 所以我创建了一个程序来计算一些东西,它目前正在控制台中运行。我决定向其中添加一个用户界面,因此我使用 NetBeans IDE 中的内置功能创建了一个 J
我有 2 个 Controller ,TEST1Controller 和 TEST2Controller 在TEST2Controller中,我有一个initialize()函数设置属性值。 如果我尝
据我所知, dependentObservable 在声明时会进行计算。但如果某些值尚不存在怎么办? 例如: var viewModel ={}; var dependentObservable1 =
我正在阅读 POODR 这本书,它使用旧语法进行默认值初始化。我想用新语法实现相同的功能。 class Gear attr_reader :chainring, :cog, :wheel de
我按照 polymer 教程的说明进行操作: https://www.polymer-project.org/3.0/start/install-3-0 (我跳过了可选部分) 但是,在我执行命令“po
很抱歉问到一个非常新手的Kotlin问题,但是我正在努力理解与构造函数和初始化有关的一些东西。 我有这个类和构造函数: class TestCaseBuilder constructor(
假设我们有一个包含 30 列和 30 行的网格。 生命游戏规则简而言之: 一个小区有八个相邻小区 当一个细胞拥有三个存活的相邻细胞时,该细胞就会存活 如果一个细胞恰好有两个或三个活的相邻细胞,那么它就
我是 MQTT 和 Android 开放附件“AOA” 的新手。在阅读教程时,我意识到,在尝试写入 ByteArrayOutputStream 类型的变量之前,应该写入 0 或 0x00首先到该变量。
我有 2 个 Controller ,TEST1Controller 和 TEST2Controller 在TEST2Controller中,我有一个initialize()函数设置属性值。 如果我尝
我有一个inotify /内核问题。我正在使用“inotify” Python项目进行观察,但是,我的问题仍然是固有的关于inotify内核实现的核心。 Python inotify项目处理递归ino
我是一名优秀的程序员,十分优秀!