Полагайтесь на конструкторы и операторы присваивания, а не на `memset` и `memcpy`
Причина
Стандартный механизм C++ для построения экземпляра типа — вызвать его конструктор. Как указано в руководстве C.41: конструктор должен создать полностью инициализированный объект. Дополнительная инициализация, такая как memcpy, не должна требоваться. Тип предоставит конструктор копирования и/или оператор присваивания копирования для надлежащего создания копии класса, сохраняя инварианты типа. Использование memcpy для копирования нетривиально копируемого типа имеет неопределенное поведение. Часто это приводит к срезанию или повреждению данных.
Хороший пример
struct base {
virtual void update() = 0;
std::shared_ptr<int> sp;
};
struct derived : public base {
void update() override {}
};
Плохой пример
void init(derived& a)
{
memset(&a, 0, sizeof(derived));
}
Это типонебезопасно и перезаписывает таблицу виртуальных функций.
Плохой пример
void copy(derived& a, derived& b)
{
memcpy(&a, &b, sizeof(derived));
}
Это также типонебезопасно и перезаписывает таблицу виртуальных функций.
Применение
- Отметьте передачу нетривиально копируемого типа
memsetилиmemcpy.
C.con: Контейнеры и другие дескрипторы ресурсов
Контейнер — это объект, содержащий последовательность объектов некоторого типа; std::vector является архетипическим контейнером. Дескриптор ресурса — это класс, который владеет ресурсом; std::vector является типичным дескриптором ресурса; его ресурс — это его последовательность элементов.
Сводка правил контейнера:
- C.100: Следуйте STL при определении контейнера
- C.101: Дайте контейнеру семантику значения
- C.102: Дайте контейнеру операции перемещения
- C.103: Дайте контейнеру конструктор списка инициализаторов
- C.104: Дайте контейнеру конструктор по умолчанию, который устанавливает его в пустой
- ???
- C.109: Если дескриптор ресурса имеет семантику указателя, предоставьте
*и->
См. также: Ресурсы