使用Union(联合体)的参考用法

9

在工作中,我一直在使用Linux和GCC编译器进行C++11和C++14的开发。在某些需要存储引用和指针的代码中,我使用了一个联合体(union)来实现,代码如下所示:(只展示重要部分)

struct MyStruct
{
    //Stuff
    union { double& x; double* x_ptr; };
    MyStruct(double& value) : x(value) {}
    //More stuff
};

我认为这段代码很清晰、易读、明确,并提供了一种方便的方法来存储可以转移到其他内容的引用。它提供易于理解的语法糖,不会影响性能,同时提高可读性。然而,当我尝试在Visual Studio 15中使用此类代码时,由于“双重&”类型的非法联合成员,代码无法编译。
  1. 这段代码是按照标准非法的,还是只是在Visual Studio 2015下非法的?
  2. 我可以让它在Visual Studio 2015中编译,还是需要提交错误报告/更改请求/其他什么东西?
  3. 在那种情况下使用联合是否是坏实践?
注意:在我的工作中,几乎所有的代码都是为Linux编写的,并使用GCC编译,对于我的特定项目,保证使用C++11,并且GCC是唯一将被使用的编译器。
编辑:请不要告诉我在联合内放置一个引用“没有意义”。当引用存储在结构体内时,它占用与指针相同的空间。此外,以下代码在clang中编译:
struct MyStruct
{
    //This will compile
    union 
    { 
        struct { double& x; }; 
        double* x_ptr; 
    };
    //This won't compile; WHY?
    /*union 
    { 
        double& x;
        double* x_ptr; 
    };*/
    MyStruct(double& val) : x(val){}
    void Repoint(double& new_value) 
    { 
        x_ptr = &new_value; 
    }
};

为什么当引用包装在匿名结构体中时,代码能够编译通过,但当它只是在联合体中时就不能? 实际示例
2个回答

13
除了 @Brian 之外: 您可以使用例如 std::reference_wrapper 而不是普通引用来使其编译:

另外:您可以使用例如 std :: reference_wrapper 而不是普通引用,以使其编译:

#include <functional>

struct MyStruct
{
    //Stuff
    union { std::reference_wrapper<double> x; double* x_ptr; };
    MyStruct(double& value) : x(value) {}
    //More stuff
};

int main()
{
    double value = 123;
    MyStruct myStruct(value);
}

实时示例


11

一个union中不能包含引用成员,这可能是因为引用不是对象,而且未指定它们是否占用存储空间,因此让引用与其他变量共享其存储空间没有多大意义。

一个union可以有成员函数(包括构造函数和析构函数),但不能有虚函数(10.3)。一个union不应该有基类,也不应该被用作基类。如果一个union包含非静态数据成员的引用类型,则程序将不合法。

([class.union]/2)


当一个结构体包含一个引用时,该引用被存储为指针。这里没有歧义。 - Alecto Irene Perez
2
@JorgePerez 可能是。但在某些情况下,它也可能被优化掉了。这不是标准规定的。 - Brian Bi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接