Читать «Стандарты программирования на С++. 101 правило и рекомендация» онлайн - страница 148
Андрей Александреску
Аналогично, функция memcmp
— неподходящий инструмент для сравнения чего-то более сложного, чем просто наборы битов. Иногда эта функция делает слишком мало (например, сравнение строк в стиле С — не то же, что и сравнение указателей, при помощи которых эти строки реализованы). А иногда, как это ни парадоксально, memcmp
делает слишком много (например, memcmp
может совершенно напрасно сравнивать байты, которые не являются частью состояния объекта, такие как заполнители, вставленные компилятором для выравнивания). В обоих случаях результат сравнения оказывается неверным.
Ссылки
97. Не используйте объединения для преобразований
Резюме
Хитрость все равно остается ложью: объединения можно использовать для получения "преобразования типа без преобразования", записывая информацию в один член и считывая из другого. Однако это еще более опасно и менее предсказуемо, чем применение reinterpret_cast
(см. рекомендацию 92).
Обсуждение
Не считывайте данные из поля объединения, если последняя запись была не в это же поле. Чтение из поля, отличного от поля, в которое производилась запись, имеет неопределенное поведение, и использование этого метода еще хуже, чем применение reinterpret_cast
(см. рекомендацию 92); в последнем случае компилятор, как минимум, может предупредить программиста и не допустить "невозможной интерпретации" наподобие указателя в char
. При использовании для этой цели объединения никакая интерпретация не приведет к ошибке времени компиляции (как и к надежному результату).
Рассмотрим фрагмент кода, предназначенного для сохранения значения одного типа (char*) и выборки битов этого значения в виде величины иного типа (long
):
union {
long intValue_;
char* pointerValue_;
};
pointerValue_ = somePointer;
long int gotcha = intValue_;
Здесь есть две проблемы.
• sizeof(long)
и sizeof(char*)
равны и что их битовые представления идентичны. Эти утверждения справедливы не для всех возможных реализаций (см. рекомендацию 91).
•
Исключения
Если две POD-структуры являются членами объединения и начинаются с полей одних и тех же типов, можно записывать одно из таких полей, а затем считывать данные из другого.
Ссылки
98. Не используйте неизвестные аргументы (троеточия)
Резюме
Наличие троеточий в С++ — опасное наследие С. Избегайте их в своих программах; используйте вместо этого высокоуровневые конструкции и библиотеки С++.
Обсуждение
Функции с переменным количеством аргументов достаточно удобны, однако использование неизвестных аргументов в стиле C — не лучший способ получения таких функций. Эти аргументы имеют много серьезных недостатков.