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


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

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

2 78

2 ответа:

группировки.

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

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

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

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