c++ - 最令人烦恼的解析和指针间接/解引用

标签 c++ pointers language-lawyer dereference most-vexing-parse

最少的代码:

struct A {
  A(int = 0) {}
};

int i = 0, *p = &i;
int* foo () { return p; }

int main () {
  A(); // calls `A::A(int=0)`
  A(i);  // calls `A::A(int=0)`

  A(*p); // <--- (1) same as local `A *p;`
  {
    A((*p));   // <--- (2) same as local `A *p;`
  }
  A (*foo());  // <--- (3) ??
  {
    A ((*foo()));  // <--- (4) ??
  }
}

预计至少 A((*p)) 会调用 A::A(int=0)。即使在 *p 周围放置多个大括号,也会将语句视为 A *p;
foo 相关语句也是如此,其中构造函数A::A(int=0) 没有被调用。 这是一个demo .

问题:

  1. 为什么连 (2) 和 (4) 都被视为声明?
  2. 语句(3)和(4)中foo的描述是什么?

最佳答案

在解析可能是声明或表达式的构造时(称为最令人烦恼的解析歧义),标准表示“解决方案是将任何可能是声明的构造视为声明”。

(2) 和(4) 都是有效的声明,因此它们必须被解析为声明。 (3) 和 (4) 都声明了 A*() 类型的函数 foo 又名“函数不带参数返回指向 A 的指针”

6.8 歧义消解 [stmt.ambig]

There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion (5.2.3) as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration. [Note: To disambiguate, the whole statement might have to be examined to determine if it is an expression-statement or a declaration. This disambiguates many examples. [Example: assuming T is a simple-type-specifier (7.1.5),

T(a)->m = 7; // expression-statement
T(a)++; //expression-statement
T(a,5)<<c; //expression-statement
T(*d)(int); //declaration
T(e)[5]; //declaration
T(f) = { 1, 2 }; // declaration
T(*g)(double(3)); // declaration

In the last example above, g, which is a pointer to T, is initialized to double(3). This is of course illformed for semantic reasons, but that does not affect the syntactic analysis. —end example]

8.2 歧义消解 [dcl.ambig.res]

The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in 6.8 can also occur in the context of a declaration. In that context, the choice is between a function declaration with a redundant set of parentheses around a parameter name and an object declaration with a function-style cast as the initializer. Just as for the ambiguities mentioned in 6.8, the resolution is to consider any construct that could possibly be a declaration a declaration. [Note: a declaration can be explicitly disambiguated by a nonfunction-style cast, by a = to indicate initialization or by removing the redundant parentheses around the parameter name. ] [Example:

struct S {
    S(int);
};

void foo(double a)
{
    S w(int(a)); // function declaration
    S x(int()); // function declaration
    S y((int)a); // object declaration
    S z = int(a); // object declaration
}

—end example]

关于c++ - 最令人烦恼的解析和指针间接/解引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17994955/

相关文章:

c++ - 将析构函数中的关键函数放在 "enhance atomicity"中?

c++ - 为二维char数组分配内存,错误: invalid conversion from ‘void*’ to ‘char**’

c - 具有包含对静态对象的引用的外部链接的内联函数定义

c++ - 显式默认的复制 ctor 生成比手写等效代码更好的代码

c++ - 重载小于运算符

c++ - 消除警告 "construction of local static object is not thread-safe"

c++ - stack pop() 导致 "reference binding to misaligned address"错误

c - 在 C : Unhandled exception : 0xC0000005: Access violation writing location. 程序不会运行

打印数组中元素数量的代码给出的元素数量小于元素数量

c++ - 重载逗号运算符*真的*会影响其操作数的评估顺序吗?