Я знаю, что вы можете подавить предупреждение «выражение без эффекта», приведя выражение к void:
int main()
{
void(2+3);
}
Если я не ошибаюсь, смысл приведения чего-то к void заключается не в приведении выражения к объекту типа void
(void
— это тип без объектов или, лучше сказать, пустой набор), а в сообщении компилятору, что мы хотим игнорировать значение выражения. Другой связанный образец:
int main()
{
(void)(2+3);
}
есть ли семантическая разница между этим и другим образцом?
И наконец:
int main()
{
void();
}
который не возвращает предупреждений (здесь Coliru test, полный педантичных вариантов); однако этот другой генерирует ошибку:
int main()
{
(void)();
}
// Error:
// main.cpp:6:9: error: expected primary-expression before 'void'
// (void)();
// ^
// main.cpp:6:9: error: expected ')' before 'void'
Что означает выражение void()
? Вы создаете временный объект типа void
, который не имеет смысла?, или вы приводите пустое выражение к void?
И вообще, я хотел бы понять полную картину об использовании void и о том, какое поведение/семантика соответствует стандарту.
int(1)
. Как и в случае с обычными конструкторами копирования, компилятор неявно выполняет преобразование из того, что вы передаете, в тип параметра конструктора копирования. Например.int(10.0)
неявно преобразует10.0
изdouble
вint
. То же самое и с псевдоконструкторомvoid(2+3)
: компилятор вставляет неявное приведение к типу void:void((void)(2+3))
. Когда вы используете синтаксисvoid()
, он использует не конструктор псевдокопий, а конструктор псевдо по умолчанию, поэтому неявное приведение отсутствует. 12.10.2014T tmp((<some-side-effect>, void(), <tmp-value>))
, чтобы избежать перегрузок оператора запятой; Я понимаю вопрос, но этот несуществующий объект в эфире кажется мне чем-то мистическим. 12.10.2014void
не-объектом. 12.10.2014T()
создается prvalue (временный, но не обязательно объект), который инициализируется значением . Инициализация значения может вызвать конструктор по умолчанию, но только в некоторых случаях. Даже для типов классов, если конструктор по умолчанию тривиален, он не вызывается для инициализации значений. 13.10.2014T()
создает значение prvalue даже для таких вещей, какvoid()
, так что это пример необъектного «временного». 13.10.2014T()
не будет правильно создавать сложные типы классов. Однако инициализация значения может выполнять инициализацию нулями (например, для фундаментальных типов и типов классов с тривиальными конструкторами по умолчанию). 13.10.2014