繁体   English   中英

放置新的STL容器,然后安全销毁

[英]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 ,条件是mT1的公共初始序列的一部分,并且T2 ; 行为就像提名了T1的相应成员一样。

其次,常见的初始序列是标准布局类型的特征:

两种标准布局结构(第9条)的常见初始序列为[...]

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

这样安全吗?

这取决于您愿意称之为安全的东西。 该代码肯定会通过对该标准的任何合理解释来调用未定义的行为。

您不能读取联盟的非活动成员,除非涉及一个公共子序列(9.3个联盟),但是这些联盟成员没有共同的初始序列,因为该概念仅针对两个标准布局结构定义(9.2类成员/ 20)工会的一个成员根本不是一个结构。 它是一个数组,因此不能有任何共同的初始序列。

这也适用于使用原始类型的类似代码,例如int x[3]; struct {int x0, x1, x2}; 甚至不能保证x2x[2]具有相同的地址。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM