放置 - 新的STL容器并在之后安全地销毁它

Get*_*ree 6 c++ destructor placement-new unions c++11

此代码实现了一个不受限制的联合,它通过名称和索引为其三个成员中的任何一个提供访问.

由于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 ;
}
Run Code Online (Sandbox Code Playgroud)

这个例子编译和工作正常(看似),但我的问题是:

  • 这样做安全吗?
  • 我可以确定没有内存泄漏吗?
  • 如果string构造函数抛出异常怎么办?是否需要捕获以便不试图破坏从未构建的对象?

注意

代码在VC2015中编译,它支持未命名的结构.请忽略这个细节.

Bar*_*rry 2

这样做安全吗?

不可以。首先,常见的初始序列规则只允许读取成员,不允许写入:

在具有 struct 类型的活动成员 (9.3) 的标准布局联合中T1,允许读取m另一个 struct 类型的联合成员的非静态数据成员,T2前提是它是和m的公共初始序列的一部分;该行为就像 的相应成员被提名一样。T1T2T1

其次,共同的初始序列是标准布局类型的一个特征:

两种标准布局结构(第 9 条)类型的共同初始序列是 [...]

并且std::string不需要是标准布局。