【问题标题】:Why does C++ allow us to surround the variable name in parentheses when declaring a variable?为什么 C++ 允许我们在声明变量时将变量名括在括号中?
【发布时间】:2015-06-22 21:52:53
【问题描述】:

例如这样的声明:

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

【问题讨论】:

标签: c++ most-vexing-parse


【解决方案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

【讨论】:

  • 并完成答案:禁止提问者询问的特定情况将需要额外的特殊情况规则。当前对() 在类型中的工作方式的定义在整个类型中是统一的。
  • 所以特殊情况适用于最棘手的解析。这是因为使用构造函数参数初始化变量的语法是后来添加的(我猜是不是很着急?)。
  • @FISOCPP 好吧。 .是的。 C++ 出现在 C 之后。 .
  • 这个答案是否同样适用于 C,而不仅仅是 C++?
  • 函数类型变量”什么?!!
【解决方案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)),你会得到你想要的
  • 此语句只创建一个临时对象,该对象在本指令结束后不再存在(我希望这是您打算做的)。

【讨论】:

  • 正如我所提到的,最初它是在析构函数中做一些事情,我想当你有一些“链接”函数来设置一些参数然后在析构函数中完成所有工作时,这是非常标准的事情。不过,感谢您提供另一种解决方法,我想写{} 是最有效的方法。
  • 尽量避免自己编造语法并使用标准中提供的语法。 &lt;front-type&gt; &lt;specification&gt; 具有误导性,而且是错误的。语法为&lt;declaration-specifier&gt; &lt;declarator&gt;
  • 你是对的 - 我没有研究标准,只是重复了我脑海中的规则。实际上在 C++11 中&lt;declaration-specifier&gt; 的作用也可以由auto 关键字来扮演,所以它甚至不总是一个类型。
  • @Pravasi Meet:如果您编辑了我的帖子的一部分并在给定的语法架构中更改了名称,请相应地更改下面 3 行的名称。否则仍有旧名称“正面类型”和“规格”,因此帖子没有任何意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-19
  • 1970-01-01
  • 2019-06-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多