2

当我声明这样一个结构时:

#pragma pack(1)
structure MyStruct{
    uint32_t first;
    uint8_t second;
};
#pragma pack()

我显然希望它会占用 5 个字节的内存。那么这样的向量将如何表现:

std::vector<MyStruct> MyVec;

或者这样的地图:

std::map<MyStruct> MyMap;

他们会服从要求的对齐吗?我可以强制 STL 结构这样做吗?

4

3 回答 3

5

附带条件是某些编译器可以#pragma完全忽略,是的,#pragma 影响类型的定义,因此将该类型存储在向量中(例如)意味着存储的内容将被打包。

#include <iostream>
#include <vector>

typedef unsigned long uint32_t;
typedef unsigned char uint8_t;

struct MyStruct0{
    uint32_t first;
    uint8_t second;
};

#pragma pack(1)
struct MyStruct{
    uint32_t first;
    uint8_t second;
};
#pragma pack()

int main(){ 
    std::vector<MyStruct0> a;

    std::vector<MyStruct> b;

    std::cout << "Unpacked size: " << sizeof(a[0]) << "\n";
    std::cout << "Packed size: " << sizeof(b[0]) << "\n";
    return 0;
}

结果:

Unpacked size: 8
Packed size: 5
于 2013-07-01T16:51:46.770 回答
5

std::vector 需要与相同类型的普通 C=style 数组布局兼容。所以它别无选择,只能将它们放置在您为结构管理的大小。

对于其他基于节点的集合,如何创建节点、出现哪些额外字节取决于实现。

于 2013-07-01T16:55:56.627 回答
1

尺寸真的是个问题吗?听起来像过早的优化。

在任何情况下,std::vector它通常(依赖于实现)包含 2 个成员变量:它的大小和指向数据的指针。因此,除非您有很多,否则打包不会有太大变化(在您要求打包数据之前不会影响任何事情,因为它无论如何都是连续的内存块,因为它必须与 C 兼容)。

对于地图,我不太确定它的内部结构,但再次打包可能不会像 IIRC 那样影响太大,它通常被实现为平衡树。再说一次,除非你有很多很多,否则在这里没有太多收获。

编辑:另外,我打开了 MSVC 向量头,似乎有忽略编译指示打包的指令(即文件顶部的编译指示推送和底部的编译指示弹出)。

于 2013-07-01T16:58:15.027 回答