Влияет ли размер объекта на тип спецификатора доступа и тип наследования? - PullRequest
9 голосов
/ 05 июля 2011

Во время ответа на один из вопросов, под моим ответом стояла ветка обсуждения .Что говорит о том, что в зависимости от спецификатора доступа (или может быть от типа наследования) private/protected/public sizeof class объект может варьироваться!

Я все еще не понимаю из их краткого обсуждения, какэто возможно?

1 Ответ

15 голосов
/ 05 июля 2011

Обратите внимание на новый язык для 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, даже если они разделены спецификаторами доступа.


(Тем не менее,Я не знаю ни о какой реализации, которая фактически использует преимущества широты, предлагаемой любым стандартом)

...