简体   繁体   English

C ++创建两个具有重叠内存的变量

[英]C++ Create two variables with overlapping memory

I have two structs , Rect and Point . 我有两个structsRectPoint 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). 您的PointRect类具有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 rxy字段的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 . 修改*pxy字段将修改r的值,而修改rxry则将修改*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: 为了使其能够与严格的别名一起使用,您需要将RectPoint都存储在一个联合中:

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". 现在pxpy在“允许在可以看到联合的完整类型的声明的任何地方检查其中任何一个的公共初始部分”的任何情况下都引用rxry 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视为无法修改指向Rectx 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: 如果您想隐藏wh ,也许您可​​以基于Rect值创建一个“临时” Point并使用此结构...那么,如果xy可以与原始值不同,则可以将当前值设置为原始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类并同时隐藏wh ,则无法执行此操作

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. 我只保留矩形,不隐藏wh成员。

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. 一种选择是让RectPoint派生,以便它继承其成员。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM