在结构/类中包装数据的快速方法

  • 本文关键字:方法 数据 包装 结构 c++
  • 更新时间 :
  • 英文 :


EDIT: 主要目的是允许将底层数据作为封装结构的一部分进行操作,而不是直接进行数据操作

当涉及到在结构中包装某些数据时,建议使用以下哪种方法:

  1. 在结构中保留一个指向数据的指针:

    new s(buf),在本地字段(s->buf = buf)中存储buf

  2. 将内存地址重新解释为结构:

    reinterpret_cast<s*>(buf)

  3. 对数据所在的内存地址使用new运算符:

    new(buf) s;

以下是这些方法的示例程序:

#include <iostream>
using namespace std;
struct s {
    int* i;
    s(int* buf) : i(buf) {}
    int getValue() { return *i * 2; }
};
struct s2 {
    int i;
    int getValue() { return i * 2; }
};
int main() {
    int buf = 10;
    s a(&buf);
    cout << "value: " << a.getValue() << ", size: " << sizeof(a) << ", address: " << &a << ", buf-address: " << &buf << endl;
    s2* a2 = new(&buf) s2;
    cout << "value: " << a2->getValue() << ", size: " << sizeof(*a2) << ", address: " << a2 << ", buf-address: " << &buf << endl;
    s2* a3 = reinterpret_cast<s2*>(&buf);
    cout << "value: " << a3->getValue() << ", size: " << sizeof(*a3) << ", address: " << a3 << ", buf-address: " << &buf << endl;
}

输出:

value: 20, size: 4, address: 0027F958, buf-address: 0027F964
value: 20, size: 4, address: 0027F964, buf-address: 0027F964
value: 20, size: 4, address: 0027F964, buf-address: 0027F964

两种尺寸&时间很重要。此外,可维护性也很重要,例如,有人可能会错误地将虚拟函数添加到s2中(这会打乱数据对齐)。

谢谢!

这些都不是什么好主意,尽管第一个经过一些修改还是可以通过的。reinterpret_cast并没有像你想象的那样工作,我也不确定你想通过新的职位实现什么。在第一个选项中存储某种类型的智能指针,以避免寿命方面的明显问题,第一个选项也不错。

还有第四种选择:只需将数据存储在一个结构中,并提供您想要的任何封装访问。

struct data {
    data(int i_) : i(i_) { }
    int i;
};
struct s {
    s(int i_) : i(i_) { }
    data i;
};

重读你的问题,似乎你的意图是让这个结构成为某个更大对象的内部细节。在这种情况下,第一个解决方案的生存期问题可能会得到解决,因此存储原始指针不是一个坏主意。不过,在没有其他细节的情况下,我仍然推荐第四种选择。

Placement-new仍将调用构造函数,如果存在此类构造函数(或在未来不知情的情况下创建),则会清除缓冲区中已经存在的任何内容,因此我认为这不是一个安全的选项。reinterpret_cast是未定义的行为,尽管它可能看起来对您有效。存储一个本地指针似乎是最好的选择,尽管你只对你要做的事情有一点点的了解

如果您在这里尝试序列化,请记住sizeof(int)和endianness等重要问题。

使用除char*之外的任何东西重新解释_ ast是一种未定义的行为。所以2/显然出局了。

1和3可以,但1/是最直接的。

您可能更喜欢封装数据,您可能希望使用指向结构或类的(void*)指针,这允许类型封装,并允许在下一版本的代码中扩展结构中的数据:

struct HiddenCode{
  int Field1;
  char Field2;
};
void transferData(void* anyptr)
{
    // this method "knows" that "anyptr" is a "HiddenCode*"
    HiddenCode* MyHiddenCode = (void*) anyptr;
    // do something else
}
void main()
{
  HiddenCode* MyHiddenCode = new HiddenCode();
  MyHiddenCode->Field1 = 5;
  MyHiddenCode->Field2 = '1';
  void* anyptr = (void*)MyHiddenCode;
  transferData(anyptr);
}

干杯。

最新更新