为什么C ++允许我们在声明变量时用括号括起变量名?

时间:2015-04-16 13:05:04

标签: c++ most-vexing-parse

例如声明:

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;之类的变量,但我从未见过有人真正使用过像这样的声明。所以我很感兴趣 - 这种可能性的目的是什么,因为现在我看到它只创造了类似于臭名昭着的#34;最令人烦恼的解析&#34;并没有添加任何有用的东西吗?

2 个答案:

答案 0 :(得分:80)

分组。

作为一个特例,请考虑您可以声明一个函数类型的变量,例如

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

答案 1 :(得分:17)

通常允许在这样的声明中使用括号,因为从语法的角度来看,声明看起来总是这样:

<front type> <specification>;

例如,在以下声明中:

int* p[2];

&#34;正面类型&#34;是int(不是int*)和&#34;规范&#34;是* p[2]

规则是你可以根据需要在&#34;规范&#34;中使用任意数量的括号。部分原因是它们有时不可避免地会消除歧义。例如:

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)),你就会得到你想要的东西
  • 这句话除了创建一个临时对象外什么都没做,这个对象在这个指令结束后停止生效(我希望这是你打算做的)。