memset
практически никогда не является правильным способом сделать это. И да, есть практическая разница (см. Ниже).
В C ++ не все может быть инициализировано с помощью литерала 0
(объекты перечислимых типов не могут быть), поэтому в C ++ общая идиома
some_struct s = {};
в то время как в C идиома
some_struct s = { 0 };
Обратите внимание, что в C = { 0 }
- это то, что можно назвать универсальным инициализатором нуля . Он может использоваться с объектами практически любого типа, так как {}
-замкнутые инициализаторы допускаются также со скалярными объектами
int x = { 0 }; /* legal in C (and in C++) */
, что делает = { 0 }
полезным в общем коде C, не зависящем от типа (например, макросах, не зависящих от типа).
Недостаток инициализатора = { 0 }
в C89 / 90 и C ++ состоит в том, что он может использоваться только как часть объявления. (C99 устранил эту проблему, введя составные литералы . Аналогичные функции появятся и в C ++.) По этой причине многие программисты могут использовать memset
, чтобы обнулить что-то в середине C89 /. 90 или C ++ код. Тем не менее, я бы сказал, что правильный способ по-прежнему без memset
, а с чем-то вроде
some_struct s;
...
{
const some_struct ZERO = { 0 };
s = ZERO;
}
...
т.е. введя «фиктивный» блок в середине кода, даже если на первый взгляд он может показаться не слишком красивым. Конечно, в C ++ нет необходимости вводить блок.
Что касается практической разницы ... Вы можете услышать, как некоторые люди говорят, что memset
будет давать те же результаты на практике, так как на практике физическая комбинация "все нули" является той, которая используется для представления нулевых значений для всех типов. , Однако, как правило, это не так. Непосредственным примером, демонстрирующим разницу в типичной реализации C ++, является тип указатель на элемент-член
struct S;
...
int S::*p = { 0 };
assert(p == NULL); // this assertion is guaranteed to hold
memset(&p, 0, sizeof p);
assert(p == NULL); // this assertion will normally fail
Это происходит из-за того, что типичная реализация обычно использует битовую комбинацию всего один (0xFFFF...
) для представления нулевого указателя этого типа. Приведенный выше пример демонстрирует реальную практическую разницу между обнулением memset
и обычным = { 0 }
инициализатором.