是什么阻止编译器消除每个特定上下文中未使用的数据成员?
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.x
和t.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。我使用了一个奇怪的例子,只观察连续的成员,因为观察前面的成员需要明确的指针算法,这在标准中有些含糊不清。我认为这样做没有实际问题,但我将其从示例中删除以将问题分开。参见 。
下例中的函数 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.x
和t.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。我使用了一个奇怪的例子,只观察连续的成员,因为观察前面的成员需要明确的指针算法,这在标准中有些含糊不清。我认为这样做没有实际问题,但我将其从示例中删除以将问题分开。参见