C++ 联合如何从对象列表中确定最大大小?

C++ 联合如何从对象列表中确定最大大小?,c++,C++,我不确定这个问题是否恰当,因为我知道怎么做,但我不知道用我不懂的东西来写问题。这是: 我有一些课程: class Animal{}; class Rabbit{}: public Animal; class Horse{}: public Animal; class Mouse{}: public Animal; class Pony{}: public Horse; 我的目标是从这个对象列表中找到最大大小,以便在以后的内存分配中使用它。我将对象的每个大小存储在一个数组中,然后取数组的最大值。

我不确定这个问题是否恰当,因为我知道怎么做,但我不知道用我不懂的东西来写问题。这是:

我有一些课程:

class Animal{};
class Rabbit{}: public Animal;
class Horse{}: public Animal;
class Mouse{}: public Animal;
class Pony{}: public Horse;
我的目标是从这个对象列表中找到最大大小,以便在以后的内存分配中使用它。我将对象的每个大小存储在一个数组中,然后取数组的最大值。我将代码发送给的上级建议我使用union,以便在预编译时找到最大大小。我觉得这个主意很好,所以我就这样做了:

typedef union
{
  Rabbit rabbitObject;
  Horse horseObject;
  Mouse mouseObject;
  Pony ponyObject;
} Size;
typedef union
{
   unsigned char RabbitObject[sizeof(Rabbit)];
   unsigned char HorseObject[sizeof(Horse)];
   unsigned char MouseObject[sizeof(Mouse)];
   unsigned char PonyObject[sizeof(Pony)];
} Interesting;
。。。因为联合根据最大的元素大小分配内存。 下一个建议是这样做:

typedef union
{
  Rabbit rabbitObject;
  Horse horseObject;
  Mouse mouseObject;
  Pony ponyObject;
} Size;
typedef union
{
   unsigned char RabbitObject[sizeof(Rabbit)];
   unsigned char HorseObject[sizeof(Horse)];
   unsigned char MouseObject[sizeof(Mouse)];
   unsigned char PonyObject[sizeof(Pony)];
} Interesting;
我的问题是:

有趣的联合如何获得对象的最大大小?对我来说,创建一个长度为sizeofclass的unsigned char类型的数组是没有意义的。为什么第二种选择能解决问题,而前一种选择却不能? 后面发生了什么,我错过了

附:条件是这样的,我不能亲自问他


提前谢谢你

假设不正确,这个问题没有意义。标准不要求活接头尺寸等于最大构件的尺寸。相反,它要求联合体的大小足以容纳最大的成员,这一点都不相同。这两种解决方案都有缺陷,因为需要确切知道最大类的大小

相反,应该使用类似的方法:

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

这些假设是不正确的,这个问题是没有意义的。标准不要求活接头尺寸等于最大构件的尺寸。相反,它要求联合体的大小足以容纳最大的成员,这一点都不相同。这两种解决方案都有缺陷,因为需要确切知道最大类的大小

相反,应该使用类似的方法:

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

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

union padding {
    char arr[sizeof (double) + 1];
    double d;
};
union padding {
    char arr[sizeof(double) + 1];
    char d[sizeof(double)];
};
这可以是sizeofdouble+1大小,也可以是sizeofdouble*2大小,因为可以对接头进行填充以使其与double的对齐

但是如果你有

union padding {
    char arr[sizeof (double) + 1];
    double d;
};
union padding {
    char arr[sizeof(double) + 1];
    char d[sizeof(double)];
};
联合体不需要双重对齐,联合体的大小很可能为sizeofdouble+1。但这并没有限制,并且大小可以大于它的最大元素

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

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

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

union padding {
    char arr[sizeof (double) + 1];
    double d;
};
union padding {
    char arr[sizeof(double) + 1];
    char d[sizeof(double)];
};
这可以是sizeofdouble+1大小,也可以是sizeofdouble*2大小,因为可以对接头进行填充以使其与double的对齐

但是如果你有

union padding {
    char arr[sizeof (double) + 1];
    double d;
};
union padding {
    char arr[sizeof(double) + 1];
    char d[sizeof(double)];
};
联合体不需要双重对齐,联合体的大小很可能为sizeofdouble+1。但这并没有限制,并且大小可以大于它的最大元素

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

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

这两种方法提供了一种找到联合体的所有对象都能容纳的最大大小的方法。我更喜欢第一种方法,因为它更清楚地说明正在做什么,第二种方法没有提供第一种方法不能满足您需求的任何东西

第一个是由各种类组成的联合,它还提供了访问联合的特定成员的能力

另见和

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

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

sizeof报告的大小将是指定的变量或类型的大小,但这也可能包括额外的未使用内存区域,以将变量填充到下一个理想的内存地址对齐。看


通常,一个类、结构或联合的大小是这样的:如果创建了该类型的数组,那么数组的每个元素都将从最有用的内存对齐开始,例如英特尔x86体系结构的双字内存对齐。此填充通常位于变量的末尾。

这两种方法提供了一种方法,可以找到联合的所有对象都能容纳的最大大小。我更喜欢第一种方法,因为它更清楚地说明正在做什么,第二种方法没有提供第一种方法不能满足您需求的任何东西

第一个是由各种类组成的联合,它还提供了访问联合的特定成员的能力

另见和

有关类的内存布局的一些讨论,请参见下面的帖子 s:

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

sizeof报告的大小将是指定的变量或类型的大小,但这也可能包括额外的未使用内存区域,以将变量填充到下一个理想的内存地址对齐。看



通常,一个类、结构或联合的大小是这样的:如果创建了该类型的数组,那么数组的每个元素都将从最有用的内存对齐开始,例如英特尔x86体系结构的双字内存对齐。这种填充通常位于变量的末尾。

在我看来,它就像一个无符号的char-RabbitObject[sizeofRabbit];和兔子一样大。我不清楚为什么你觉得数组没有意义。我就是不明白。我需要所有对象的最大大小,所以对我来说,创建一个包含每个对象的一个实例的并集是合乎逻辑的,然后使用SizeFunion以获得最大值。为什么我需要sizeofclass的无符号字符数组?如果可以使用c++17,那么返回到第一个实现的constexpr版本可能会更清楚。类似于constexpr std::array size={{sizeofRabbit,sizeofHorse,…};constexpr std::size\t maxSize=std::max\u elementstd::beginsizes,std::endsize;在我看来,它就像一个未签名的char-RabbitObject[sizeofRabbit];和兔子一样大。我不清楚为什么你觉得数组没有意义。我就是不明白。我需要所有对象的最大大小,所以对我来说,创建一个包含每个对象的一个实例的并集是合乎逻辑的,然后使用SizeFunion以获得最大值。为什么我需要sizeofclass的无符号字符数组?如果可以使用c++17,那么返回到第一个实现的constexpr版本可能会更清楚。类似于constexpr std::array size={{sizeofRabbit,sizeofHorse,…};constexpr std::size\t maxSize=std::max\u elementstd::beginsizes,std::endsize;哪种假设?关于工会?请纠正我,我真的很想理解这一点,即使这是一件简单的事情。@lukuss,是的。假设联合大小等于最新元素的大小是不正确的。最新?不,更大。我的意思是,如果我有一个带有和无符号字符的并集和一个整数大小的并集,那么它就是整数大小。对吗?改进:模板结构最大大小:std::integral_constant@Caleth,说得好。总是忘记它的初始值设定项列表版本。会加上什么假设?关于工会?请纠正我,我真的很想理解这一点,即使这是一件简单的事情。@lukuss,是的。假设联合大小等于最新元素的大小是不正确的。最新?不,更大。我的意思是,如果我有一个带有和无符号字符的并集和一个整数大小的并集,那么它就是整数大小。对吗?改进:模板结构最大大小:std::integral_constant@Caleth,说得好。总是忘记它的初始值设定项列表版本。两种工会方法都是错误的。联盟没有义务让它的大小等于最大的元素。@SergeyA我知道。我在解释为什么上级说了他们所做的,但无论如何这是个错误。只要涉及到标准值,数组和无数组都会产生相同的结果-大小足以容纳最大的成员,但不一定完全相等。@NathanOliver上级架构师建议使用Union而不是数组,数组是我的解决方案,因此我对此无能为力。我只是想知道为什么我的工会是错的,而他的工会是对的。“现在我发现两人都错了。”卢库斯说,这很可悲。如果可以的话,试着说服他们放弃,因为他们依赖的行为将来可能会改变。两种工会方法都是错误的。联盟没有义务让它的大小等于最大的元素。@SergeyA我知道。我在解释为什么上级说了他们所做的,但无论如何这是个错误。只要涉及到标准值,数组和无数组都会产生相同的结果-大小足以容纳最大的成员,但不一定完全相等。@NathanOliver上级架构师建议使用Union而不是数组,数组是我的解决方案,因此我对此无能为力。我只是想知道为什么我的工会是错的,而他的工会是对的。“现在我发现两人都错了。”卢库斯说,这很可悲。如果可以的话,试着说服他们放弃它,因为他们依赖于将来可能改变的行为。类现在是空的。但是如果这些类将有方法和属性呢?它们肯定会有。如果我们在类中有特定的构造函数呢?我的第一种方法仍然有效吗?这是我的上级推荐第二个的原因之一union@lukuss见下文p
排序和讨论:,[对象在内存中看起来像什么?重复],以及。@lukuss我真的看不出数组版本有什么好处,因为sizeof将提供与联合中的类相同的大小。类方法不是类内存分配的一部分,尽管虚拟函数创建的vtable是。基本的经验法则是,类的不变部分(如方法)不属于类内存分配的一部分,而类的可变部分(如数据)和特定于对象的管理数据(如vtable)属于类内存分配的一部分,用于实例化该类的对象。对齐是最有用的对于架构ABI,每个成员都是真正为其编译的。填充可能出现在除开头之外的任何位置,因为继承的C行为意味着在结构中可以将指向该结构的指针强制转换为指向其第一个成员的指针;这是C语言中“手工”完成的单向继承。类现在是空的。但是如果这些类将有方法和属性呢?它们肯定会有。如果我们在类中有特定的构造函数呢?我的第一种方法仍然有效吗?这是我的上级推荐第二个的原因之一union@lukuss请参阅以下帖子和讨论:,[对象在内存中看起来像什么?重复],以及。@lukuss我真的不认为数组版本有任何好处,因为sizeof将提供与联合中的类相同的大小。类方法不是类内存分配的一部分,尽管虚拟函数创建的vtable是。基本的经验法则是,类的不变部分(如方法)不属于类内存分配的一部分,而类的可变部分(如数据)和特定于对象的管理数据(如vtable)属于类内存分配的一部分,用于实例化该类的对象。对齐是最有用的对于架构ABI,每个成员都是真正为其编译的。填充可能出现在除开头之外的任何位置,因为继承的C行为意味着在结构中可以将指向该结构的指针强制转换为指向其第一个成员的指针;这是C语言中“手工”完成的单向继承。