[英]Placement-new an STL container and destroying it safely afterwards
此代码实现了一个不受限制的联合,该联合通过名称和索引提供对其三个成员中任何一个的访问。
由于std::string
是非平凡的构造和销毁的,因此我需要为union
提供特殊的构造函数和析构函数。
#include <iostream>
#include <string>
using namespace std ;
union MyUnion{
string parts[3] ;
struct{ string part1, part2, part3 ; } ;
MyUnion(){
new(parts+0) string ; //constructs the 3 strings in-place
new(parts+1) string ;
new(parts+2) string ;
}
~MyUnion(){
parts[0].~string() ; //calls string's destructor
parts[1].~string() ;
parts[2].~string() ;
}
} ;
int main(){
MyUnion u ;
u.part1 = "one" ; //access by name
u.part2 = "two" ;
u.part3 = "three" ;
cout << u.parts[0] << endl ; //access by index
cout << u.parts[1] << endl ;
cout << u.parts[2] << endl ;
}
此示例可以编译并正常运行(貌似),但是我的问题是:
string
的构造函数抛出异常怎么办? 是否需要抓住它以便不试图破坏从未构造的对象? 该代码在VC2015中编译,它确实支持未命名的结构。 请忽略该细节。
这样安全吗?
不会。首先,通用的初始序列规则仅允许读取成员,而不能写入:
在具有结构类型
T1
的活动成员(9.3)的标准布局联合中,允许读取结构类型T2
的另一个联合成员的非静态数据成员m
,条件是m
是T1
的公共初始序列的一部分,并且T2
; 行为就像提名了T1
的相应成员一样。
其次,常见的初始序列是标准布局类型的特征:
两种标准布局结构(第9条)的常见初始序列为[...]
并且std::string
不需要是标准布局。
这样安全吗?
这取决于您愿意称之为安全的东西。 该代码肯定会通过对该标准的任何合理解释来调用未定义的行为。
您不能读取联盟的非活动成员,除非涉及一个公共子序列(9.3个联盟),但是这些联盟成员没有共同的初始序列,因为该概念仅针对两个标准布局结构定义(9.2类成员/ 20)工会的一个成员根本不是一个结构。 它是一个数组,因此不能有任何共同的初始序列。
这也适用于使用原始类型的类似代码,例如int x[3];
和struct {int x0, x1, x2};
。 甚至不能保证x2
和x[2]
具有相同的地址。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.