86

例如这样的声明:

int (x) = 0;

甚至是:

int (((x))) = 0;

我偶然发现了这一点,因为在我的代码中我碰巧有一个类似于以下的片段:

struct B
{
};

struct C
{
  C (B *) {}
  void f () {};
};

int main()
{
  B *y;
  C (y);
}

显然我想构造一个对象C,然后在它的析构函数中做一些有用的事情。但是,编译器将其视为具有类型C (y);的变量声明,因此它会打印有关重新定义的错误。有趣的是,如果我将它写成或类似的东西,它将按预期编译。当然,最好的现代解决方法是在构造函数调用中使用。yCyC (y).f ()C (static_cast<B*> (y)){}

因此,正如我在那之后发现的那样,可以声明变量int (x) = 0;,甚至是int (((x))) = 0;,但我从未见过有人真正使用这样的声明。所以我很感兴趣——这种可能性的目的是什么,因为现在我看到它只会创建类似于臭名昭著的“最令人烦恼的解析”的案例并且没有添加任何有用的东西?

4

2 回答 2

81

分组。

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

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
于 2015-04-16T13:11:06.560 回答
17

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

<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))你会得到你想要的
  • 该语句只创建一个临时对象,该对象在该指令结束后不再存在(我希望这是您打算做的)。
于 2015-04-16T13:14:12.673 回答