调试器友好的零成本命名引用数组中的特定位置

Gam*_*Gam 7 c++ c++14

struct A
{
    int a   = 1;
    short b = 2;
    char c  = 3;
}

struct B
{
    using arr_type = array<A,3>;
    char asd = 0;
    A a1;  
    A a2;
    A a3;

    // is this safe to use to loop trough all 3 elements?
    arr_type* p1 = reinterpret_cast<arr_type*>(&a1);

    // or maybe this one?
    A* p2 = &a1;
};
Run Code Online (Sandbox Code Playgroud)

我可以安全地使用p1p2循环播放a1...a3吗?

B b;

for (int i = 0; i < 3; i++)
{
     cout << p1[i];
     cout << p2[i];
}
Run Code Online (Sandbox Code Playgroud)

它不是一个简单的数组的原因是因为我希望每个"项目"都有一个正确的名称.

我可以使用union方法,但是C++禁止匿名结构(虽然这对我来说不是问题,因为MSVC支持这个并且GCC似乎也支持它);

union E
{
    A arr[3];
    struct {
        A a1;
        A a2;
        A a3;
    };
};
Run Code Online (Sandbox Code Playgroud)

以下显然是安全的,但每个引用的开销为4字节.我不喜欢哪个.(加上初始化参考文献的成本..)

struct B
{
    char asd;
    A arr[3];  
    A& a1 = arr[0];
    A& a2 = arr[1];
    A& a3 = arr[2];
};
Run Code Online (Sandbox Code Playgroud)

而这个没有开销,但对于我的具体情况,这还不够好.

struct B
{
    char asd;
    A arr[3];  
    A& a1() { return arr[0] };
    A& a2() { return arr[1] };
    A& a3() { return arr[2] };
};
Run Code Online (Sandbox Code Playgroud)

我将a1, a2, a3经常使用这些名称,如果它们是visual studio中的函数调用,则更难调试它们.而且,我将要经常使用这些字段,所以我希望能够轻松地检查它们的值.

Hos*_*ork 7

struct B
{
     using arr_type = array<A,3>;
     char asd = 0;
     A a1;  
     A a2;
     A a3;

     // is this safe to use to loop trough all 3 elements?
     arr_type* p1 = reinterpret_cast<arr_type*>(&a1);
 };
Run Code Online (Sandbox Code Playgroud)

结构需要自然地对齐它们的类型,数组也是如此,但我不知道有任何规则说它们必须是相同的对齐点.

如果该结构布局边界像这样和数组边界成员这样的规则是相同的-这将仅适用于标准的布局结构:

/sf/answers/503287501/

如果您执行以下操作,所有投注都将被取消:

private:
    A a1;
    A a2;
public:
    A a3;
Run Code Online (Sandbox Code Playgroud)

我想如果它包含任何从标准布局开关上掉下来的东西,那么所有的赌注都会关闭.因为从一开始就有问题,我会说甚至不这样做.

(我也想知道#pragma pack()数组和结构会产生什么样的差异...不是#pragmas在标准中,我只是想知道.)

union E
{
    A arr[3];
    struct {
        A a1;
        A a2;
        A a3;
    };
};
Run Code Online (Sandbox Code Playgroud)

不,arr[N]而且aN不等同.关于如何在联合中使用初始序列以便在C++中进行兼容读取,有一些细微的细节......但这只是在具有兼容序列的结构之间.它没有提到结构和数组:

通过联合键入C和C++中的结构

我将经常使用那些a1,a2,a3名称,如果它们是visual studio中的函数调用,则更难调试它们.而且,我将要经常使用这些字段,所以我希望能够轻松地检查它们的值.

"以下显然是安全的,但每个引用的开销为4字节 "

在实践中看起来你是对的,今天的GCC没有优化它(根据你的链接):

https://godbolt.org/g/6jAtD5

http://ideone.com/zZqfor

这令人失望,他们可以进行优化,因为标准中没有任何内容表明他们必须占用空间.它们内部指向结构,并且它们在结构的生命周期内不会改变.: - /

您对可以优化的功能访问的投诉是它对调试器不够友好.为什么不两个都做?

struct B
{
    char asd;
    A arr[3];

    A& a1() { return arr[0] }
    const A& a1() const { return arr[0]; }
    A& a2() { return arr[1] };
    const A& a2() const { return arr[1]; }
    A& a3() { return arr[2] };
    const A& a3() const { return arr[2]; }

#if !defined(NDEBUG)
    A& a1_debug = arr[0];
    A& a2_debug = arr[1];
    A& a3_debug = arr[2];
#endif
};
Run Code Online (Sandbox Code Playgroud)

如果调试数据结构的调试器友好性特征对您很重要...可能会很好地利用时间来学习如何为您的环境编写自定义调试器助手,例如:

http://doc.qt.io/qtcreator/creator-debugging-helpers.html

我想这是否值得,取决于你有多少经常有这种担忧.