Кое-что о совершенно пустом классе

#include <iostream>

using namespace std;

class Empty{
char omg[0];
};

int main()
{
Empty em1, em2;
Empty set[100];
cout << sizeof(Empty) << " " << sizeof(em1) << " " << sizeof(em2) << endl;
cout << (long*)&em1 << " " << (long*)&em2 << endl;

cout << "total numbers of element is: " << sizeof(set)/sizeof(*set) << endl;

return 0;
}

Его вывод:

0 0 0

0xbff36ad0 0xbff36ac8

количество элементов: 4

Результаты так удивительны.

Как показано выше, Empty — это класс, его размер и все его объекты равны 0, почему?

Может быть, я думаю, потому что размер пустого класса равен 1, а когда класс не пустой, его размер определяется членами, но здесь его член особенный, это массивы нулевой длины, а размер этого массива равен 0, так что размер класса и объектов — все 0.

Это только мое предположение. Когда программа работает, мы видим, что два объекта имеют адрес, а адрес различен.

Вот мой вопрос: если объект 0 размера может быть реализован, почему стандарт C ++ утверждает, что пустые объекты имеют sizeof () = 1, то это для «Чтобы гарантировать, что адреса двух разных объектов будут разными»Почему размер пустого класса не равен нулю? , но теперь у нас есть другой адрес в качестве выхода , как это происходит?

Более того, независимо от размера набора массивов, вывод последней строки всегда равен 4, почему?

Спасибо 🙂

PS: я запускаю эту программу на MacOS, и компилятор Apple LLVM версии 5.1 (clang-503.0.40) (на основе LLVM 3.4svn)

9

Решение

Я сделаю удар, поскольку никто более опытный не имеет:

Как показано выше, Empty — это класс, его размер и все его объекты равны 0, почему?

Массивы нулевого размера запрещены стандартом, поэтому в отношении стандарта sizeof(Empty) это бессмысленное выражение, вы уже находитесь в сфере неопределенного поведения.

Вот мой вопрос: если объект 0 размера может быть реализован, […] Почему размер пустого класса не равен нулю? , но теперь у нас есть другой адрес в качестве выхода , как это происходит?

Как и выше, объект размера 0 не может существовать в допустимой стандартной программе на С ++ (за исключением базового класса субобъекты).

Ваш компилятор допускает это как расширение стандарта, и до тех пор, пока вы используете это расширение в той области действия, для которой оно предназначено (то есть как хак для предварительного гибкого элемента массива), у вас не должно быть никаких проблем, хотя ваш код не портативный. Однако в приведенном выше примере не показано, как использовать массивы нулевого размера (не говоря уже о том, что в c ++ есть лучшие конструкции для обработки этих ситуаций в любом случае).

Ваш компилятор достаточно умен, чтобы предоставить отдельные адреса для em1 а также em2, но вы должны найти, что все элементы set на самом деле имеют тот же адрес.

Более того, независимо от размера набора массивов, вывод последней строки всегда равен 4, почему?

Так как ваш компилятор считает sizeof(Empty) и массивы Empty чтобы быть нулем, вы делитесь на ноль, что является неопределенным поведением. Вы можете обнаружить, что ваша программа вылетает, если вы отключите оптимизацию, например, с помощью GCC ваша программа вылетает с -O0 но не с -O1,

1

Другие решения


По вопросам рекламы [email protected]