在struct / class中包装数据的快速方法

时间:2011-06-20 15:00:30

标签: c++

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

在结构中包含一些数据时,建议采用以下哪种方法:

  1. 保持指向结构中数据的指针:

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

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

    reinterpret_cast<s*>(buf)

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

    new(buf) s;

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

    #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(这会弄乱数据对齐)。

    谢谢!

4 个答案:

答案 0 :(得分:4)

这些都不是很好的想法,虽然第一个可以通过一些修改。 reinterpret_cast并不像您认为的那样有效,而且我不确定您要通过新的展示方式实现什么目标。在第一个中存储某种智能指针以避免生命周期中的明显问题,并且第一个选项也不错。

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

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

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

重读你的问题,看起来好像你的意图是这个结构是一个更大的对象的内部细节。在这种情况下,第一个解决方案的生命周期问题可能会得到解决,因此存储原始指针不是一个坏主意。但是,如果没有其他细节,我仍然会推荐第四个选项。

答案 1 :(得分:3)

放置新的仍然调用构造函数,如果存在这样的构造函数(或者将来在不知不觉中创建),则消除缓冲区中的任何内容,因此我认为这不是一个安全的选项。 reinterpret_cast是未定义的行为,即使它似乎对您有用。存储本地指针似乎是最好的选择,尽管你只是对你想要做的事情进行了非常小的介绍。

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

答案 2 :(得分:1)

将reinterpret_cast与char *以外的任何内容一起使用是一种未定义的行为。所以2 /显然已经出局了。

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

答案 3 :(得分:1)

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

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);
}

干杯。