看看这个简单的代码:
struct Point {
int x;
int y;
};
void something(int *);
int main() {
Point p{1, 2};
something(&p.x);
return p.y;
}
我希望main
的返回值可以优化到return 2;
,因为something
无法访问p.y
,它只能得到一个指向p.x
的指针。
但是,没有一个主要的编译器优化main
的返回值2
。戈德博尔特。
标准中是否有某些内容允许something
修改p.y
,如果我们只允许访问p.x
?如果是,这是否取决于Point
是否具有标准布局?
如果我使用something(&p.y);
和return p.x;
怎么办?
这是完全明确的:
void something(int *x) {
reinterpret_cast<Point*>(x)->y = 42;
}
Point
对象 (p
( 及其x
成员是指针可相互转换的,来自 [basic.compound]:
在以下情况下,两个对象a和b是指针可相互转换的:
- [...]
一个是标准布局类对象,另一个是该对象的第一个非静态数据成员,- 或者,如果该对象没有非静态数据成员,则该对象的任何基类子对象 ([class.mem](,或者:
- [...]
如果两个对象是指针可互转换的,则它们具有相同的地址,并且可以通过
reinterpret_cast
从指向另一个对象的指针获取指向一个对象的指针。
该reinterpret_cast<Point*>(x)
是有效的,并且最终会得到一个指向p
的指针。因此,直接修改它是可以的。如您所见,标准布局部分和第一个非静态数据成员部分非常重要。
虽然它不像有问题的编译器,但如果您传递指向p.y
的指针并返回p.x
,则会优化额外的负载。