Ответ 1
Приведение в действие void используется для подавления предупреждений компилятора. Стандарт говорит в §5.2.9/4, говорит
Любое выражение может быть явно преобразовано в тип "cv void". значение выражения отбрасывается.
Часто используемый оператор типа (void)x;
позволяет подавлять предупреждения о неиспользуемой переменной x
. Но если я попробую компилировать следующее, я получаю некоторые результаты, которые я не совсем понимаю:
int main()
{
int x;
(short)x;
(void)x;
(int)x;
}
Компилируя это с помощью g++, я получаю следующие предупреждения:
$ g++ test.cpp -Wall -Wextra -o test
test.cpp: In function ‘int main()’:
test.cpp:4:13: warning: statement has no effect [-Wunused-value]
(short)x;
^
test.cpp:6:11: warning: statement has no effect [-Wunused-value]
(int)x;
^
Итак, я пришел к выводу, что кастинг на void
сильно отличается от кастинга на любые другие типы, будь то целевой тип, такой же, как decltype(x)
или что-то другое. Мое предположение о возможных объяснениях:
(void)x;
, но не другие броски будут подавлять предупреждения. Все утверждения одинаково не влияют.void x;
не является допустимым выражением, а short x;
-.Какие из них, если они есть, являются более правильными? Если нет, то как объяснить разницу в предупреждениях компилятора?
Приведение в действие void используется для подавления предупреждений компилятора. Стандарт говорит в §5.2.9/4, говорит
Любое выражение может быть явно преобразовано в тип "cv void". значение выражения отбрасывается.
Это утверждение:
(void)x;
Говорит "Игнорировать значение x". Нет такого типа, как void
- это отсутствие типа. Так что это очень отличается от этого:
(int)x;
Что говорит: "Обращайтесь с x как с целым числом". Когда полученное целое число игнорируется, вы получаете предупреждение (если оно включено).
Когда вы игнорируете что-то, что ничто, это не считается проблемой GCC - и не без оснований, поскольку casting to void является идиоматическим способом игнорировать переменную явно в C и С++.
Стандарт не предусматривает создание предупреждения ( "диагностика" в стандартном) для неиспользуемых локальных переменных или параметров функции. Аналогичным образом, он не предусматривает, как такое предупреждение может быть подавлено. Выделение выражения переменной void
для подавления этого предупреждения стало идиомой в сообществе C и более поздних версий С++, потому что результат не может использоваться каким-либо образом (кроме, например, (int)x
), поэтому маловероятно, что соответствующий код просто отсутствует. Например:.
(int)x; // maybe you meant f((int)x);
(void)x; // cannot have intended f((void)x);
(void)x; // but remote possibility: f((void*)x);
Лично я считаю, что это соглашение слишком неясное, поэтому я предпочитаю использовать шаблон функции:
template<typename T>
inline void ignore(const T&) {} // e.g. ignore(x);
Идиоматический способ игнорировать параметры функции - это, однако, опустить свое имя (как видно выше). Частое использование, которое я использую для этой функции, - это когда мне нужно указать параметр функции в условно скомпилированном коде, например assert
. Я нахожу, например. следующее более разборчивое, чем использование #ifdef NDEBUG
:
void rate(bool fantastic)
{
assert(fantastic);
ignore(fantastic);
}
Возможное использование:
auto it = list_.before_begin();
for (auto& entry : list_)
{
(void)entry; //suppress warning
++it;
}
Теперь итератор 'it' указывает на последний элемент