确保std::string正确对齐
Assure correct alignment on std::string
编译此标头:
// myheader.h
class MyClass {
MyClass();
~MyClass();
unsigned int mMyUint;
bool bMyBool;
std::string sMyString;
};
使用Visual Studio 2010/W4(我被告知要这样做),目标x64给了我以下warning C4121
:
'MyClass' : alignment of a member was sensitive to packing
,指的是std::string sMyString
所在的行。微软的官方帮助建议使用#pragma pack(x)
,其中x
是1、2、4,取决于在其结构/类中使用的成员。
不,我想知道std::string使用哪种对齐方式?我的想法是std::string和编译器都不是独立于平台的。有没有办法解决这个问题,特别是考虑到其他可能有任何其他结盟的成员?
最好是一个独立于编译器的(甚至是可移植的)解决方案。
更新:关于jalf提供的非常有用的答案:不,在这个文件中,我没有使用#pragma pack(x)
。我在另一个结构中使用了它,在那里我使用了位字段,我看到这些字段在不使用#pragma pack(x)
时被填充。现在,我只是被同样的陷阱吓了一跳,因为我不知道Microsoft编译器是如何解析std::string
的。
独立于编译器且可移植的解决方案正是您向我们展示的代码。如果您不做任何破坏它的事情,编译器会负责正确对齐所有内容。(例如使用需要特殊对齐的SIMD类型,或使用#pragma pack
)
如果您使用的是#pragma pack
,那么:
- 你为什么不给我们看
- 不要
如果您在/W4上向我们显示的代码给您任何警告,请归咎于Microsoft。该代码正确、可移植且安全(与使用pack
杂注的代码不同)。
微软对/W4上的警告有一些奇怪的想法。大多数编译器只对看起来可能包含错误的内容发出警告。
微软有一大堆警告,基本上是说"我没有理由怀疑这段代码有问题,但如果你用不同的方式编写,它可能会包含一个错误",这纯属无稽之谈。
对于其他编译器,我通常建议在启用所有警告的情况下进行编译。在微软的编译器上,这是不可行的。(尽管您可以使用/W4,并选择性地静音特定的无意义警告)
我认为他们特别告诉你的是,该结构包含填充字节(因此,如果确实使用了#pragma pack
,它将更改类的布局,并且受影响的类成员之一将对此更改"敏感")。
如果可能的话,考虑重新排列类成员,使它们按大小降序排列。这样可以提供更紧凑的类布局,只在类的末尾添加填充(如果有的话)。
但是您当前使用的类定义没有任何错误。
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- 如何创建一个QTableWidgetItem,用长文本右对齐,左边有省略号
- 我可以检测和更改 gcc/g++ 中结构的当前数据对齐设置吗?
- 64位机器上的C++内存对齐
- 为什么我可以将变量存储在不是其最小对齐方式的倍数的地址?
- 使 std::vector 分配对齐内存的现代方法
- C++ cout 将双精度对齐到精度 2 并正确对齐
- 在 64 位边界上对齐C++结构数组?
- 使用 g++7 构建的代码在访问未对齐的内存时崩溃
- 在 capnp FlatArrayMessageReader 的对齐内存缓冲区中接收 zmq 消息
- 是否值得对齐变量?
- 初始化派生结构的基部分/意外打包派生结构字段以对齐基结构的间隙
- 对齐和对齐的实际用例C++关键字
- 如何减少代码的运行时间以对齐文本?
- 指向包含对齐 C 结构C++类的 C 指针的对齐问题
- Linux C++ 中的页面对齐内存分配
- C++ 类层次结构中的"对齐"是什么意思?
- 运行时错误:引用绑定到类型"int"的未对齐地址0xbebebebebebebec6,这需要 4 个字节对齐 (stl_vector.h)
- 数据结构对齐:为什么Char和STD :: String的数组不同
- 确保std::string正确对齐