联合如何根据对象列表确定最大大小?

时间:2018-03-14 14:34:55

标签: c++

我不确定这个问题是否妥善,因为我理解了这一点,但我不知道用我不理解的东西来写问题。这是:

我有一些课程:

class Animal{};
class Rabbit{}: public Animal;
class Horse{}: public Animal;
class Mouse{}: public Animal;
class Pony{}: public Horse;

我的目标是从此对象列表中找到最大大小,以便在之后的内存分配中使用它。我已将对象的每个sizeof存储在一个数组中,然后获取数组的最大值。上级(我发送代码以供审核)建议我使用联合以在编译前时找到最大大小。这个想法对我来说似乎很好,所以我这样做了:

typedef union
{
  Rabbit rabbitObject;
  Horse horseObject;
  Mouse mouseObject;
  Pony ponyObject;
} Size;

...因为union根据最大的元素分配内存。 下一个建议是这样做:

typedef union
{
   unsigned char RabbitObject[sizeof(Rabbit)];
   unsigned char HorseObject[sizeof(Horse)];
   unsigned char MouseObject[sizeof(Mouse)];
   unsigned char PonyObject[sizeof(Pony)];
} Interesting;

我的问题是:

Interesting union如何获得对象的最大大小?对我来说,创建一个长度为sizeof(class)的unsigned char类型的数组是没有意义的。为什么第二种选择会解决问题而以前的联盟并不能解决问题呢? 背后发生了什么,我想念?

PS:条件是这样的,我不能亲自问这个人。

提前谢谢

3 个答案:

答案 0 :(得分:6)

这些假设是不正确的,这个问题没有实际意义。标准不要求联合大小等于最大成员的大小。相反,它要求联合大小足够来保存最大的成员,这根本不相同。两种解决方案都存在缺陷,需要确切知道最大类的大小。

相反,应该使用类似的东西:

template<class L, class Y, class... T> struct max_size
        : std::integral_constant<size_t, std::max(sizeof (L), max_size<Y, T...>::value)> { };
template<class L, class Y> struct max_size<L, Y>
        : std::integral_constant<size_t, std::max(sizeof (L), sizeof (Y))> { };

正如@Caleth在下面建议的那样,可以使用std::max(和模板变量)的初始化列表版本缩短它:

template<class... Ts>
constexpr size_t max_size_v = std::max({sizeof(Ts)...});

答案 1 :(得分:0)

你建议你使用数组版本,因为联合可以有填充。例如,如果你有

union padding {
    char arr[sizeof (double) + 1];
    double d;
};

这可以是sizeof(double) + 1大小,也可以是sizeof (double) * 2,因为可以填充联合以使其与double对齐{{3} })。

但是如果你有

union padding {
    char arr[sizeof(double) + 1];
    char d[sizeof(double)];
};

联合不需要双重对齐,并且联合最有可能具有sizeof(double) + 1Live example)的大小。尽管如此,这个尺寸可能不会超过它的最大元素。

如果你想确保最大尺寸我建议使用

auto max_size = std::max({sizeof(Rabbit), sizeof(Horse), sizeof(Mouse), sizeof(Pony)});

答案 2 :(得分:0)

这两种方法提供了一种方法来找到联合的所有对象都适合的最大大小。我更喜欢第一个,因为它更清楚地表明正在做什么,第二个没有提供第一个不能满足你的需求。

第一个是由各个类组成的联盟,它也能够访问联盟的特定成员。

另请参阅Is a struct's address the same as its first member's address? 以及sizeof a union in C/C++ Anonymous union and struct [duplicate]

有关类内存布局的一些讨论,请参阅以下帖子:

由于编译器可以自由地添加各种组件的大小以便在特定的内存地址边界上对齐变量,因此联合的大小可能大于数据的实际大小。一些编译器提供了一个pragma或其他类型的指令来指示编译器是否应该完成类,结构或联合成员的打包。

sizeof()报告的大小将是指定的变量或类型的大小,但是这又可以包括额外的未使用的存储区域以将变量填充到下一个期望的存储器地址对齐。请参阅Why isn't sizeof for a struct equal to the sum of sizeof of each member?

通常会调整类,结构或联合的大小,以便在创建类型的数组时,数组的每个元素都将从最有用的内存对齐开始,例如Intel x86体系结构的双字内存对齐。此填充通常位于变量的末尾。