将联合与非平凡类型的数组一起使用

问题描述 投票:0回答:1

如果我有一个包含非平凡类型数组的联合(例如

std::string

using namespace std;

struct MyUnion {
    union {
        char c;
        string s[5];
    };
    MyUnion() {}
    ~MyUnion() {}
};

仅初始化该数组的一部分并使用它是否合法(根据 C++ 标准)?

MyUnion mu;

// construct 2 strings using placement new
new (&mu.s[0]) string();
new (&mu.s[1]) string();

// do something with the strings
do_something(mu.s[0]);
do_something(mu.s[1]);

// destruct 2 strings
mu.s[0].~string();
mu.s[1].~string();

由于某种原因,这个问题已被标记为重复,但这个问题具体是关于 arrays 并且仅初始化数组的一部分。提议的重复项不能回答这个问题。

c++ arrays unions
1个回答
0
投票

仅初始化该数组的一部分并使用它是否合法(根据 C++ 标准)?

是的,但有一些麻烦。

MyUnion mu;
new (&mu.s[1]) string(); // #1

指针运算仅在数组对象上合法,并且#1处没有数组对象。因此,

mu.s[1]
本身就是未定义的行为。

在 C++20 之前,如果不启动所有

mu.s
子对象的生命周期,就无法启动数组
string
的生命周期。

使用 C++20,我们可以做到

MyUnion mu;
new (&mu.s) char[sizeof(mu.s)]; // #2
new (&mu.s[1]) string();

创建

char
数组是指定隐式创建对象的一项操作。 #2 之后,隐式创建了一个
string
数组,从而使
mu.s[1]
合法。

使用 C++23,首选解决方案是

MyUnion mu;
std::start_lifetime_as<decltype(MyUnion::s)>(&mu.s);
new (&mu.s[1]) string();
© www.soinside.com 2019 - 2024. All rights reserved.