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


84

例如这样的声明:

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;但是我从未见过有人实际使用过这样的声明。因此,我很感兴趣-这种可能性的目的是什么,因为到目前为止,我看到它只会创建类似于臭名昭著的“最令人烦恼的分析”的案例,并且没有添加任何有用的信息?


可能性的“目的”可能是简化解析器。
molbdnilo 2015年


1
@GSerg有趣的是,我的问题的文本如何回答您链接的问题中第二个问题的问题,因为我提供了允许此类声明导致意外结果的示例:)
Predelnik


走进了这个陷阱:不知道互斥体已被注释掉,然后不小心写了不正确的括号声明。// std :: mutex std :: unique_lock <std :: mutex>(m_mutex);
服务劳里森(Laurijssen)'18年

Answers:


80

分组。

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

int f(int);

现在,您将如何声明一个指向此类事物的指针?

int *f(int);

不,不行!这被解释为函数returning int*。您需要添加括号以使其以正确的方式进行解析:

int (*f)(int);

同样处理数组:

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

13
为了完成答案:禁止询问者所询问的特殊情况将需要一个额外的特殊情况规则。当前()在类型中如何工作的定义在整个类型中是统一的。
约瑟夫·曼斯菲尔德

因此,特殊情况适用于最麻烦的解析。这是因为稍后添加了使用构造函数参数初始化变量的语法(我想很急吗?)。
AnArrayOfFunctions

1
@FISOCPP好。。是。C ++紧随C之后。。
iheanyi

这个答案是否同样适用于C,而不仅仅是C ++?
kdbanman 2015年

函数类型的变量”是什么?!
curiousguy 2015年

17

通常允许在此类声明中使用括号,因为从句法的角度来看,声明始终看起来像这样:

<front type> <specification>;

例如,在以下声明中:

int* p[2];

“ front type”是int(不是int*),“ specification”是* 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))加上括号-您将得到想要的
  • 该语句除了创建一个临时对象外什么都不做,在该指令结束后,该对象将不再存在(我希望这是您打算做的事情)。

1
正如我提到的,起初它是在析构函数中执行某些操作,但是我想当您具有一些用于设置某些参数然后在析构函数中完成所有工作的“链接”函数时,这是很标准的事情。不过,感谢您提供另一种解决方法,我想写作{}毕竟是最有效的一种方法。
2015年

4
尽量避免自己编写语法,并使用标准中提供的语法。<front-type> <specification>是误导和错误的。语法是<declaration-specifier> <declarator>
史蒂夫·考克斯

您是对的-我没有研究标准,只是从脑海里重复了这一规则。实际上,在C ++ 11中,<declaration-specifier>也可以通过auto关键字来扮演角色,因此它甚至不总是一个类型。
Ethouris

@Pravasi Meet:如果您已经编辑了我的帖子的一部分,并且在给定的语法模式中更改了名称,请相应地在下面的三行中更改名称。否则,仍然有旧名称“ front type”和“ specification”,因此该帖子没有任何意义。
Ethouris
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.