标准::p空气<U,V>对准控制



我注意到std::pair在试图将其保存到二进制文件中时发生了一件令人不快的事情:std::对与一个单词对齐。就处理器效率而言,它可能很有用,但需要更多的存储空间,所以我想将std::pair的对齐模式切换到1字节。我的编译器是MS VC++2012。

#include <iostream>
int main( )
{
    struct S_a { double a; size_t b; };
#pragma pack(1)
    struct S_wa { double a; size_t b; };
    std::cout << sizeof( size_t ) << 'n';                          // 4
    std::cout << sizeof( double ) << 'n';                          // 8
    std::cout << sizeof( std::pair< size_t, size_t > ) << 'n';     // 8
    std::cout << sizeof( std::pair< double, size_t > ) << 'n';     // 16 - bad
    std::cout << sizeof( S_wa ) << 'n';                            // 12 - good
    std::cout << sizeof( S_a ) << 'n';                             // 16
    std::cout << sizeof( std::pair< double, double > ) << 'n';     // 16
}

我试过这个,但不起作用:

#pragma pack(1)
    typedef std::pair< double, size_t > Q;
    std::cout << sizeof( Q ) << 'n';                               // 16

std::pair基本上减少为:

class xxx
{
   T1 _t1;
   T2 _t2;
};

两个成员的对齐是由定义模板本身时生效的对齐定义的,而不仅仅是当它用于实例化实例时。

STL的Microsoft实现使用符号_CRT_PACKING来定义用于所有STL组件的包装。默认情况下,包装设置为8。如果在包含定义std::pair<utility>)的标头之前您自己定义了这个符号,那么理论上您可以覆盖包装并设置自己的。

注意调用库或采用标准封装的其他代码时可能遇到的潜在问题。

很抱歉,pack杂注在这种情况下不适用。你可以

#define _CRT_PACKING 1
#include <utility>

这可能会导致各种各样的问题。其中之一是某些API,尤其是低级API,期望数据以某种方式对齐。并不是所有人都足够聪明,能够处理不适合的情况;这可能会导致不礼貌的崩溃。

如果您真的希望对象像这样串行化,请自己处理std::pair<U,V>的串行化(仅限示例):

template<typename U, typename V>
void paircpy(char *dest, const std::pair<U, V> &pair) {
    memcpy(buffer, &pair.first, sizeof(U));
    memcpy(buffer + sizeof(U), &pair.second, sizeof(V));
}

您可能希望很好地处理memcpy不正确的数据类型的特殊情况。

对于任何严肃的项目,你真正应该做的是以一种可移植的方式串行化对象,这样它们就可以检索并优雅地处理浮点、签名数据类型的不同编码、指针、数组、STL容器以及任何其他不可能或不足以简单转储对象内存的事情。

阅读C++常见问题解答并开发自己的串行化模块,这些模块不仅仅是将对象的内存表示转储到文件中。

或者,您可以使用预打包的便携式解决方案对等数据类型进行串行化

  • Boost.Serialization
  • 谷歌的协议缓冲区
  • XDR库
  • JSON或XML

好吧,完全不同的"解决方案",这可能是一个好主意,也可能不是,但嘿,如果它有效,我是谁来阻止你知道。它与其他答案有着相同的注意事项,但允许你挑选你的毒药。

为您关心的类型执行std::pair的部分专用化,使用特定定义的pragma包,例如charint:

namespace std {
#pragma pack( /* ... whatever you want ... */ )
template<> struct pair<char,int> {
  char first;
  int second;
};
}

有了定义,你可以触摸它,你可以影响包装。同样,只有当你愿意为所有相关类型做这件事,并记住其他海报提到的注意事项时,这才是好的。

并且您正在使用的库很有可能是疯狂的,并决定在pair中放入更多库的其他部分所依赖的内容,但您可能不需要担心

最新更新