Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Placement-new an STL container and destroying it safely afterwards

This code implements an unrestricted union which provides access by name and by index to any of its three members.

Since std::string is non-trivially constructed and destroyed, I need to provide special constructor and destructor for the 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 ;
}

This example compiles and works fine (seemingly), but my questions are:

  • Is it safe to do this?
  • Can I be sure that there will be no memory leaks?
  • What if string's constructor throws an exception? Does that need to be caught so as to not try to destroy an object that was never constructed?

Note

The code compiles in VC2015, which does support unnamed structs. Please disregard that detail.

like image 986
GetFree Avatar asked Apr 27 '17 22:04

GetFree


1 Answers

Is it safe to do this?

No. First, the common initial sequence rule only allows reading of members, not writing:

In a standard-layout union with an active member (9.3) of struct type T1, it is permitted to read a non-static data member m of another union member of struct type T2 provided m is part of the common initial sequence of T1 and T2; the behavior is as if the corresponding member of T1 were nominated.

Secondly, common initial sequence is a trait of standard layout types:

The common initial sequence of two standard-layout struct (Clause 9) types is [...]

and std::string is not required to be standard-layout.

like image 82
Barry Avatar answered Sep 28 '22 03:09

Barry