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

Например, объявление, например:

int (x) = 0;

Или даже это:

int (((x))) = 0;

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

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<B*> (y)), он будет компилироваться по назначению. Лучшее современное решение - использовать {} в вызове конструктора, конечно.

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

Ответ 1

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

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

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

Ответ 2

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

<front type> <specification>;

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

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)), и вы получите то, что захотите.
  • Этот оператор ничего не делает, кроме создания временного объекта, который перестает жить после окончания этой инструкции (я надеюсь, что это именно то, что вы намеревались сделать).