Обратите внимание на новый язык для C ++ 11 ниже
В C ++ 03 есть язык, который делает это возможным, 9.2 [class.mem]/ 12 (выделено мной):
Нестатические члены-данные класса (не объединенного), объявленного без промежуточного спецификатора доступа , распределяются так, чтобы более поздние члены имели более высокие адреса в пределахобъект класса. Порядок распределения нестатических элементов данных, разделенных спецификатором доступа, не указан (11.1).Требования выравнивания реализации могут привести к тому, что два смежных элемента не будут выделяться сразу после друг друга;То же самое можно сказать о требованиях к пространству для управления виртуальными функциями (10.3) и виртуальными базовыми классами (10.1).
Поэтому, учитывая это определение:
class Foo
{
char a; //8 bits
// a must come before b, so 3 bytes of padding have to go here to satisfy alignment
int b; //32 bits
char c; //8 bits
// 24 bits of padding required to make Foo a multiple of sizeof(int)
};
в системе с 32-разряднымint
), компилятору не разрешается изменять порядок c
до b
, заставляя вставлять дополнительные отступы между a
и b
и после c
до концаобъект (изготовление sizeof(Foo) == 12
).Однако для этого:
class Foo
{
char a;
public:
int b;
public:
char c;
};
a
и (b
и c
) разделяются спецификатором доступа, поэтому компилятор может выполнить такое переупорядочение, делая
memory-layout Foo
{
char a; // 8 bits
char c; // 8 bits
// 16 bits of padding
int b; // 32 bits
};
sizeof(Foo) == 8
.
В C ++ 11 язык немного меняется.N3485 9.2 [class.mem] / 13 говорит (выделено мое):
Нестатические члены данных (не объединяющего) класса с тем же контролем доступа (пункт 11)распределяются так, чтобы более поздние члены имели более высокие адреса в объекте класса. Порядок распределения нестатических элементов данных с различным контролем доступа не определен (раздел 11).Требования выравнивания реализации могут привести к тому, что два смежных элемента не будут выделяться сразу после друг друга;также могут возникнуть требования к пространству для управления виртуальными функциями (10.3) и виртуальными базовыми классами (10.1).
Это означает, что в C ++ 11 в приведенном выше примере (разделенном 3 открытыми),Компилятору по-прежнему не разрешено выполнять переупорядочение.Это должно быть что-то вроде
class Foo
{
char a;
public:
int b;
protected:
char c;
};
, в котором a
, b
и c
имеют различный контроль доступа.
Обратите внимание, что в C ++ 11правила, с определением типа:
class Foo
{
char a;
public:
int b;
protected:
char c;
public:
int d;
};
компилятор должен поставить d
после b
, даже если они разделены спецификаторами доступа.
(Тем не менее,Я не знаю ни о какой реализации, которая фактически использует преимущества широты, предлагаемой любым стандартом)