- 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/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!