Почему C ++ позволяет нам окружать имя переменной в круглых скобках при объявлении переменной?

Например, такая декларация, как:

int (x) = 0; 

Или даже это:

 int (((x))) = 0; 

Я наткнулся на это, потому что в моем коде у меня был fragment, похожий на следующий:

 struct B { }; struct C { C (B *) {} void f () {}; }; int main() { B *y; C (y); } 

Очевидно, я хотел построить объект C который затем сделает что-то полезное в своем деструкторе. Однако, как это бывает, компилятор рассматривает C (y); как объявление переменной y с типом C и, следовательно, печатает ошибку о переопределении y . Интересно, что если я напишу его как C (y).f () или как-то вроде C (static_cast (y)) он будет компилироваться по назначению. Лучшее современное решение – использовать {} в вызове конструктора, конечно.

Так, как я выяснил после этого, можно объявить переменные типа int (x) = 0; или даже int (((x))) = 0; но я никогда не видел, чтобы кто-то действительно использовал объявления вроде этого. Поэтому мне интересно – какова цель такой возможности, потому что на данный момент я вижу, что она только создает случай, похожий на пресловутый «самый неприятный синтаксический анализ» и не добавляет ничего полезного?

Группировка.

В качестве конкретного примера рассмотрим, что вы можете объявить переменную типа функции, такую ​​как

 int f(int); 

Теперь, как бы вы объявили указатель на такую ​​вещь?

 int *f(int); 

Нет, не работает! Это интерпретируется как функция, возвращающая int* . Вам нужно добавить в круглые скобки, чтобы он правильно разобрал:

 int (*f)(int); 

То же самое касается массивов:

 int *x[5]; // array of five int* int (*x)[5]; // pointer to array of five int 

В таких объявлениях обычно разрешено использовать круглые скобки, потому что декларация, с синтаксической точки зрения, всегда выглядит так:

  ; 

Например, в следующем объявлении:

 int* p[2]; 

«Тип фронта» – это int (не int* ), а «спецификация» – * p[2] .

Правило состоит в том, что вы можете использовать любое количество круглых скобок по мере необходимости в части «спецификация», потому что они иногда неизбежны для устранения неоднозначности. Например:

 int* p[2]; // array of 2 pointers to int; same as int (*p[2]); int (*p)[2]; // pointer to an array of 2 ints 

Указатель на массив является редким случаем, однако в той же ситуации у вас есть указатель на функцию:

 int (*func(int)); // declares a function returning int* int (*func)(int); // declares a pointer to function returning int 

Это прямой ответ на ваш вопрос. Если ваш вопрос касается утверждения типа C(y) , то:

  • Поместите круглые скобки вокруг всего выражения – (C(y)) и вы получите то, что хотите
  • Это заявление ничего не делает, кроме создания временного объекта, который перестает жить после окончания этой инструкции (я надеюсь, что это именно то, что вы намеревались сделать).
Давайте будем гением компьютера.