Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: Union Destructor

A union is a user-defined data or class type that, at any given time, contains only one object from its list of members. Suppose all the possible candidate members are needed to be allocated dynamically. For Eg.

// Union Destructor
#include <string>
using namespace std;

union Person
{
private:
    char* szName;
    char* szJobTitle;
public:
    Person() : szName (nullptr), szJobTitle (nullptr) {}
    Person (const string& strName, const string& strJob)
    {
        szName = new char[strName.size()];
        strcpy (szName, strName.c_str());

        szJobTitle = new char [strJob.size()];
        strcpy (szJobTitle, strJob.c_str());    // obvious, both fields points at same location i.e. szJobTitle
    }
    ~Person()   // Visual Studio 2010 shows that both szName and szJobTitle
    {           // points to same location.
        if (szName) {
            delete[] szName;     // Program crashes here.
            szName = nullptr;  // to avoid deleting already deleted location(!)
        }
        if (szJobTitle)
            delete[] szJobTitle;
    }
};

int main()
{
    Person you ("your_name", "your_jobTitle");
    return 0;
}

Above program get crashed at 1st delete statement in ~Person (at moment when szName contains valid memory location, WHY?).

What will be the correct implementation for the destructor?

Same way, how to destruct a class object, if my class contains an union member (how to wrtie destructor for class including a Union)?

like image 352
masT Avatar asked Mar 25 '23 06:03

masT


1 Answers

You can only use one member of the union at a time because they share the same memory. In the constructor, however, you initialize both members, which overwrites each other, and then in the destructor you end up releasing it two times. You're trying to use it as if it were a struct (based on the names of the fields you need to use a struct).

Nevertheless, if you need a union then you probably need a struct as a kind of envelope which has some id representing the member being used, as well as a constructor and a destructor that handles the resources.

Also - your arrays are too small. size() returns the number of characters, but if you use char* as your string type then you need space for the null-character (\0) to handle termination.

If you need unions, try using Boost.Variant. It is a lot easier to use than normal unions.

like image 126
Jan Herrmann Avatar answered Apr 01 '23 09:04

Jan Herrmann