gpt4 book ai didi

c++ - 不受限制的 union 是否需要放置新的和构造函数定义?

转载 作者:可可西里 更新时间:2023-11-01 17:39:03 25 4
gpt4 key购买 nike

我看到的无限制 union 的例子似乎总是在构建时使用新的放置。有关 C++11 功能的维基百科文章在 union 的构造函数中使用了 new 放置。

https://en.wikipedia.org/wiki/C%2B%2B11#Unrestricted_unions

#include <new> // Required for placement 'new'.

struct Point {
Point() {}
Point(int x, int y): x_(x), y_(y) {}
int x_, y_;
};

union U {
int z;
double w;
Point p; // Illegal in C++03; legal in C++11.
U() {new(&p) Point();} // Due to the Point member, a constructor definition is now required.
};

这里有必要用placement new吗?例如,这段代码使用 gcc 和 valgrind 编译时没有警告,当 union 用于保存字符串时,没有显示内存泄漏:

struct HasUnresUnion
{
enum { Int, String } tag;

HasUnresUnion(int i)
: tag(Int),
as_int(i)
{}

HasUnresUnion(std::string str)
: tag(String),
as_str(std::move(str))
{}

~HasUnresUnion()
{
using std::string;
if (tag == String)
as_str.~string();
}

union
{
int as_int;
std::string as_str;
};
};

这里似乎没有任何歧义,所以我不明白为什么标准会禁止这样做。这是法典吗?当 union 未初始化(而不是被分配给)时,是否需要放置新的? union 中的构造函数是否需要?我肯定见过没有自己的构造函数的不受限制的 union ,但维基百科明确指出这是必需的。

最佳答案

简介

您显示的代码段非常安全;法律允许您在初始化类 union 类时初始化一个非静态数据成员。


例子

维基百科文章有一个使用 placement-new 的例子,因为他们在可以直接初始化某个成员的点之后写入成员。

union A {
A () { new (&s1) std::string ("hello world"); }
~A () { s1.~basic_string<char> (); }
int n1;
std::string s1;
};

不过,前面的代码段在语义上等同于以下代码段,其中我们明确声明 A::s1 应在构造 A 时进行初始化。

union A {
A () : s1 ("hello world") { }
~A () { s1.~basic_string<char> (); }
int n1;
std::string s1;
};

阐述

在您的代码片段中,您的类中有一个匿名 union (这使您的类成为一个类 union 类),这意味着除非您初始化一个 union 的成员在类的初始化期间 — 您必须在以后使用 placement-new 来初始化它们。


标准怎么说?

9.5/1 -- <b>Unions</b> -- [class.union]p1

In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.

3.8/1 -- <b>Object lifetime</b> -- [basic.life]p1

[...]

The lifetime of an object of type T begins when:

  • storage with the proper alignment and size for type T is obtained, and
  • if the object has non-trivial initialization, its initialization is complete.

The lifetime of an object of type T ends when:

  • if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or
  • the storage which the object occupies is reused or released.

关于c++ - 不受限制的 union 是否需要放置新的和构造函数定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33058717/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com