Что означает предупреждение "padding class" Tester с 4 байтами?

Для этого упрощенного тестового примера:

#include <map>

class Tester {
    int foo;
    std::map<int, int> smap;
};

int main() {
    Tester test; 
    return 0;
}

Я получаю следующее предупреждение компилятора:

$ clang++ -std=c++98 -Weverything test.cc 
test.cc:5:24: warning: padding class 'Tester' with 4 bytes to align 'smap' [-Wpadded]
    std::map<int, int> smap;
                       ^

Может ли кто-нибудь объяснить, что означает это предупреждение, и как я должен его решить?

Ответы

Ответ 1

Здесь нет настоящей проблемы. В C и С++ компилятору разрешено вставлять дополнения после элементов структуры, чтобы обеспечить лучшее выравнивание и, таким образом, обеспечить более быстрый доступ к памяти. В этом случае, похоже, решил поместить smap на 8-байтовое выравнивание. Поскольку int почти наверняка четыре байта, предупреждение сообщает вам, что в середине структуры есть четыре байта потраченного пространства.

Если бы было больше членов структуры, то одна вещь, которую вы могли бы попробовать, заключалась бы в том, чтобы переключить порядок определений. Например, если у вашего Tester были члены:

 struct Tester {
     int foo;
     std::map<int, int> smap;
     int bar;
 };

тогда было бы целесообразно разместить два интервала рядом друг с другом, чтобы оптимизировать выравнивание и избежать потраченного впустую пространства. Однако в этом случае у вас есть только два члена, и если вы переключите их, то компилятор, вероятно, добавит четыре байта заполнения в конец структуры, чтобы оптимизировать выравнивание Tester при размещении внутри массива,

Ответ 2

Я предполагаю, что вы компилируете это в 64-разрядной системе.

В 64-битных системах указатели составляют 8 байтов. Компиляторы будут выровнять элементы структуры с естественными границами, поэтому 8-байтовый указатель начнет со смещения в структуре, кратном 8 байтам.

Поскольку int всего четыре байта, компилятор вставил 4 байта "заполнения" после foo, так что smap находится на 8-байтовой границе.

Изменить: хотя smap не является указателем, а <<24 > , применяется такая же логика. Я не уверен, какие точные правила для выравнивания объектов, но то же самое происходит.

Что делать? Ничего. Ваш код отлично работает, компилятор просто сообщает вам, что это произошло. Там абсолютно не о чем беспокоиться. -Weverything означает включение всех возможных предупреждений, что, вероятно, является чрезмерным для большинства компиляций.