Использование (void) перед вызовом функции
Возможный дубликат:
литье неиспользуемых возвращаемых значений в void
Какова цель (void)
перед вызовом функции, например
(void)func1();
Я предполагаю, что это то же самое, что просто вызвать func1();
Поэтому вызов (void)
просто позволяет другим программистам знать, что тип возвращаемого значения будет проигнорирован, например, если func1()
имел тип возврата int
, или компилятор может выполнить некоторые оптимизации для функции? Возможно, в этом есть еще одна причина - это даже законный С++ или, возможно, это остатки C, видимые в каком-то унаследованном коде.
Спасибо
Ответы
Ответ 1
Приведение в void может иметь семантический эффект в одном случае: где значение является операндом оператора запятой и переопределяет оператор запятой, литой в void будет подавлять его:
struct S {
int operator,(int) { return 0; }
};
std::cout << (S(), 42) << '\n'; // prints '0'
std::cout << ((void) S(), 42) << '\n'; // prints '42'
Ответ 2
Он предотвращает предупреждение, если какая-либо функция объявлена с атрибутом: "Предупреждать, если возвращаемое значение не используется/не проверено"
Возможно, дубликат Предупреждение: игнорирование возвращаемого значения 'scanf', объявленного с атрибутом warn_unused_result
Подробнее о документации gcc: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html (warn_unused_result)
Ответ 3
Это очень мало. Он явно превращает линию в выражение void, то есть выражение, которое используется только для его побочных эффектов и значение которого отбрасывается. Таким образом, строки
func1();
и
(void)func1();
сделает то же самое. Может быть какая-то оптимизация, которая может быть выполнена, если компилятор знает, что значение выражения не используется, но вполне вероятно, что компилятор может понять это с явным (void) или без него.
Он может использоваться как форма документации, где программист пытается сделать очевидным, что они не используют значение выражения.
Ответ 4
Еще одно странное использование заключается в том, чтобы позволить функции неизвестного типа возврата использоваться рядом с оператором ,
в качестве оператора последовательности. То есть, decltype( f(), g() )
, где вы хотите сказать, что "f
может работать с ()
, как может g
, и я хочу, чтобы этот тип был типом, который g()
возвращает". Однако, если f()
возвращает такой тип, что operator,
перегружен, результат будет неожиданным.
Итак, вы делаете decltype( void(f()), g() )
и отбрасываете возвращаемое значение f()
перед вызовом operator,
, поэтому вам гарантированно получить встроенный оператор последовательности вместо неизвестного типа переопределения.