对象联盟与指针联盟

时间:2015-05-11 08:37:36

标签: c++ c++11

如果我有两个联合线结构:

struct A {
    A() {}
    ~A() {}
    union {
        vector<int> vi;
        vector<double> db;
    };
};

struct B {
    union {
        vector<int> * vi;
        vector<double> * db;
    };
};

我知道我必须以不同的方式使用它们,例如:

A a;
new (&a.vi) vector<int>;

VS

B b;
b.vi = new vector<int>();

除此之外,使用第一种方法(unrestricted union)到第二种方法(只是保持指向当前向量的指针)有什么好处吗?或者它们在功能和性能方面是否完全相同,唯一不同的是我如何使用它们?

编辑:原始代码是简洁的示例,没有编译,我在A结构中添加A() {}~A() {}以使其正确且可编译。

2 个答案:

答案 0 :(得分:3)

  

我在<div ng-repeat="result in SearchService.getResults()"></div> 结构中添加了A() {}~A() {},以使其正确且可编译。

添加构造函数和析构函数使您的代码可编译,但它没有使其正确。原始示例中固有的问题仍然存在:编译器不知道如何处理A后面的内存。

两个载体都管理着自己的记忆。 union管理指向vi的指针,而int管理指向db的指针。两个向量都放在内存中的相同位置,因此它们的指针是共享的。在分配,复制或销毁double时,编译器不知道要调用哪些函数 - AA::vi s。

虽然您可以通过定义资源管理的所有特殊函数(构造函数/复制构造函数/移动构造函数/析构函数)来使其工作,但这是一个非常简单的练习,会导致代码非常脆弱。问题是每次向A::db添加新成员时代码都必须更改,但编译器无法提醒您。旧代码将编译,但只要您分配新成员并复制包含它的联合,它就会导致未定义的行为。

答案 1 :(得分:1)

通常,使用值或指针之间的区别在于,如果使用指针,则必须管理所有权。拥有一个成员意味着成员类将在析构函数中自动处理它的破坏,并在其复制/移动构造函数和赋值运算符中进行复制。

然而,当使用 unrestricted union 时,编译器不会为联盟成员中那些非常重要的函数生成special member functions

std::vector的情况下,这些特殊成员函数包括 all

这意味着你必须自己定义这些函数,无论你是否使用成员(因为编译器不能为你做)或指针(因为指针的默认所有权不是你想要的)如果您使用new)。

明显的区别在于成员是在单独的分配中还是在对象本身中驻留在堆上,这对vector来说可能不太重要,因为大多数对象无论如何都会驻留在堆上。

我个人会避免使用不受限制的联盟,除非我有一个很好的理由,保存一个vector(三个指针)的空间可能不够好。