是什么阻止编译器消除每个特定上下文中未使用的数据成员?

What is stopping the compiler from eliminating data members unused in each particular context?

下例中的函数 foo()optimized_foo() 是否存在不等价的情况?

struct Test
{
    int     x;
    int     y;
    int     z;
};

// Some external function. Implementation unknown.
void bar(int& arg);

void foo()
{
    Test      t;
    t.x = 3;
    t.y = 4;
    t.z = 5;
    bar(t.y);
}

void optimized_foo()
{
    int       t_y = 4;
    bar(t_y);
}

只是所有主要的x86_64编译器(gcc 10.2,clang 10.0,msvc 19.24)在为[=11=生成的汇编代码中保留了t.xt.z的初始化] 即使在最高优化级别。即使那些成员显然没有被使用。 他们有理由吗?

我是否正确假设 bar() 被赋予对结构的一个数据成员的引用,没有合法途径获得对其他成员的 pointer/reference?标准对此有何规定?

bar可以通过引用[expr.unary.op]获取成员的地址。然后该函数可以复制相邻成员的对象表示的字节。

void bar(int& arg) {
    constexpr auto size      = sizeof(Test);
    constexpr auto offset    = offsetof(Test, y);
    constexpr auto remaining = size - offset;
    unsigned char buffer[remaining];
    
    std::memcpy(buffer, &arg, remaining);
}

在函数结束时,缓冲区包含 Test 对象的某些成员的对象表示。鉴于 bar 是外部定义的,编译器在编译 foo.

时无法知道其他成员的内存是否被观察到。

注意:offsetof 仅有条件地支持非标准布局类型。有问题的 class 是标准布局。

[basic.types]

For any object (other than a potentially-overlapping subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes ([intro.memory]) making up the object can be copied into an array of char, unsigned char, or std​::​byte ([cstddef.syn]). If the content of that array is copied back into the object, the object shall subsequently hold its original value.

The object representation of an object of type T is the sequence of N unsigned char objects taken up by the object of type T, where N equals sizeof(T). ...


P.S。我使用了一个奇怪的例子,只观察连续的成员,因为观察前面的成员需要明确的指针算法,这在标准中有些含糊不清。我认为这样做没有实际问题,但我将其从示例中删除以将问题分开。参见