[英]C++ Create two variables with overlapping memory
I have two structs
, Rect
and Point
. 我有两个
structs
, Rect
和Point
。 I cannot change their implementation, regrettably. 遗憾的是,我无法更改其实现。
The definition of Rect is: Rect的定义是:
typedef struct Rect
{
int x, y;
int w, h;
} Rect;
The definition of Point
is: Point
的定义是:
typedef struct Point
{
int x, y;
} Point;
I would like to keep a single Rect, effectively, but keep the w
/ h
members hidden. 我想有效地保留一个Rect,但是将
w
/ h
成员隐藏起来。
I wondered if it was possible to create a Point object using the same address in memory such that the x
/ y
memory is shared between each object? 我想知道是否可以使用内存中的相同地址创建Point对象,以便每个对象之间共享
x
/ y
内存?
I have tried using placement new
, and it didn't seem to work, as well as reassigning the address, which obviously didn't work either. 我尝试使用
placement new
,它似乎没有用,并且重新分配了地址,这显然也没有用。
Anyone have any ideas? 有人有想法么? I know this probably isn't the best practice, but it would be a neat trick and make things a lot simpler to work with.
我知道这可能不是最佳做法,但这将是一个巧妙的窍门,使事情处理起来更加简单。
hnefatl 赫内法特
You should hide your Rect inside your own class, providing the interface you need. 您应该将Rect隐藏在自己的类中,并提供所需的接口。 Something like:
就像是:
class MyRect
{
private:
Rect _rect;
public:
MyRect(const Rect& rect);
int& x() { return _rect.x; }
int& y() { return _rect.y; }
}
C++ has the concept of layout compatible. C ++具有布局兼容的概念。 Your
Point
and Rect
classes are layout-compatible as they have a common initial prefix, and they are standard-layout (or plain old data in C++03). 您的
Point
和Rect
类具有Rect
初始前缀,并且它们是标准布局(或C ++ 03中的普通旧数据),因此它们与布局兼容。
This means 这意味着
Rect r = {1,2,3,4};
Point* p = &reinterpret_cast<Point*>(&r);
generates a Point
pointer p
that points to the x
and y
fields of the Rect r
. 生成指向Pointt
r
的x
和y
字段的Point
指针p
。 Modifying the x
and y
fields of *p
will modify the values in r
, and modifying rx
and ry
will modify the values in *p
. 修改
*p
的x
和y
字段将修改r
的值,而修改rx
和ry
则将修改*p
的值。 Well, sort of. 好吧,有点。
The downside is the concept of aliasing and strict aliasing. 缺点是别名和严格别名的概念。 If you turn off strict aliasing in your compiler, it will lose some optimizations, but the above will work.
如果在编译器中关闭严格的别名,它将失去一些优化,但是上面的方法仍然有效。
To get it to work with strict aliasing working you need to store both your Rect
and your Point
in a union: 为了使其能够与严格的别名一起使用,您需要将
Rect
和Point
都存储在一个联合中:
union MyUnion {
Rect r;
Point p;
};
MyUnion u = Rect{1,2,3,4};
and now px
and py
refer to rx
and ry
in any context where "it is permitted to inspect the common initial part of any of them anywhere that a declaration of the complete type of the union is visible". 现在
px
和py
在“允许在可以看到联合的完整类型的声明的任何地方检查其中任何一个的公共初始部分”的任何情况下都引用rx
和ry
。 So where MyUnion
can be seen, you are safe -- but where it cannot be seen, the compiler is free to treat a pointer-to- Point
modifying x
as not being able to modify the pointer-to- Rect
's x
. 因此,在可以看到
MyUnion
地方,您是安全的-但是,在看不到MyUnion
地方,编译器可以自由地将修改x
的指针指向Point
视为无法修改指向Rect
的x
。 This is important for optimization purposes, as without it reordering unchanged sub expressions becomes next to impossible. 这对于优化目的很重要,因为如果不重新排序,不变的子表达式将几乎变得不可能。
If you wanna hide w
and h
, maybe you can create an "ad hoc" Point
based on Rect
values and use this structure... then, if x
and y
can be different than originals you can set current values to original Rect
variable: 如果您想隐藏
w
和h
,也许您可以基于Rect
值创建一个“临时” Point
并使用此结构...那么,如果x
和y
可以与原始值不同,则可以将当前值设置为原始Rect
变量:
Rect original_rect;
// ...
Point point;
point.x = original_rect.x;
point.y = original_rect.y;
// code that use Point instead of Rect
// ...
// Set current values to original variable
original_rect.x = point.x;
original_rect.y = point.y;
On the other hand, if you need to use Rect
class and hide w
and h
at the same time... you cannot do it 另一方面,如果您需要使用
Rect
类并同时隐藏w
和h
,则无法执行此操作
Based on the comments and answers, it seems this is impossible. 根据评论和答案,这似乎是不可能的。 Oh well, would've been a nice trick with pointers!
哦,对了,指针指针将是一个很好的技巧!
I'll just keep the rect and not hide the w
and h
members. 我只保留矩形,不隐藏
w
和h
成员。
Thanks to all who answered :) 感谢所有回答:)
hnefatl 赫内法特
PS The code I'm using is written in C, and I'm using C++ to interact with it. PS我正在使用的代码是用C编写的,并且我正在使用C ++与之交互。 Sorry, forgot to mention that :/
对不起,忘了提及:/
PPS Thanks for the link explaining a union Joachim, I'd never got round to learning about them! PPS感谢您为解释约阿希姆工会的链接提供帮助,我永远也无法了解他们!
An option is to let the Rect
derive from Point
so that it inherits its members. 一种选择是让
Rect
从Point
派生,以便它继承其成员。
typedef struct Rect: struct Point
{
int w, h;
} Rect;
and use pointers of the type you like when you want. 并在需要时使用所需类型的指针。
Another option is to keep the original types and use wild casts, like 另一种选择是保留原始类型并使用狂野的演员表,例如
struct Point* MyPseudoPointPtr= (struct Point*)&MyRect;
This will work with references too 这也适用于参考
struct Point& MyPseudoPoint= *(struct Point*)&MyRect;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.