这两个版本的代码有什么区别?
What is the difference between these two versions of code?
此代码导致编译错误(最烦人的解析)
#include <iostream>
class A {
int a;
public:
A(int x) :a(x) {}
};
class B {
public:
B(const A& obj) { std::cout << "B\n";}
void foo() {std::cout << "foo\n";}
};
int main()
{
int test = 20;
B var(A(test)); //most vexing parse
var.foo();
return 0;
}
但是如果我通过20
而不是test
(A(20)
而不是A(test)
),就没有编译错误。
#include <iostream>
class A {
int a;
public:
A(int x) :a(x) {}
};
class B {
public:
B(const A& obj) { std::cout << "B\n";}
void foo() {std::cout << "foo\n";}
};
int main()
{
int test = 20;
//B var(A(test));
B var(A(20)); //ok works fine
var.foo();
return 0;
}
为什么这不被认为是最令人烦恼的解析?这两个代码版本有什么区别?
一个变量可以这样定义
type(name)
正因为如此
B var(A(test));
声明一个名为 var
的函数,该函数 returns 一个 B
并接受一个名为 test
的 A
。在
B var(A(20));
如果您尝试做同样的事情,A
参数将被称为 20
,这不是一个有效的变量名。因为它不能是我们知道它是一个值的变量的名称,所以我们正在构造一个名为 var
类型 B
的变量,其值为 A(20)
.
最令人头疼的解析问题是语法问题,而不是语义问题。在语法上,A(test)
归结为 identifier : OPEN_PAREN : identifier : CLOSE_PAREN
。在上下文中,这是不明确的,因为第二个标识符可能是变量名或类型名。编译器必须选择一种方式来解释这个标记序列,而且没有一个是不正确的。
相比之下,A(20)
归结为 identifier : OPEN_PAREN : integer_literal : CLOSE_PAREN
。整数文字不能解释为标识符,因此无法将其解释为类型名。因此,它必须被解析为一个表达式,该表达式初始化一个 A
.
类型的对象
此代码导致编译错误(最烦人的解析)
#include <iostream>
class A {
int a;
public:
A(int x) :a(x) {}
};
class B {
public:
B(const A& obj) { std::cout << "B\n";}
void foo() {std::cout << "foo\n";}
};
int main()
{
int test = 20;
B var(A(test)); //most vexing parse
var.foo();
return 0;
}
但是如果我通过20
而不是test
(A(20)
而不是A(test)
),就没有编译错误。
#include <iostream>
class A {
int a;
public:
A(int x) :a(x) {}
};
class B {
public:
B(const A& obj) { std::cout << "B\n";}
void foo() {std::cout << "foo\n";}
};
int main()
{
int test = 20;
//B var(A(test));
B var(A(20)); //ok works fine
var.foo();
return 0;
}
为什么这不被认为是最令人烦恼的解析?这两个代码版本有什么区别?
一个变量可以这样定义
type(name)
正因为如此
B var(A(test));
声明一个名为 var
的函数,该函数 returns 一个 B
并接受一个名为 test
的 A
。在
B var(A(20));
如果您尝试做同样的事情,A
参数将被称为 20
,这不是一个有效的变量名。因为它不能是我们知道它是一个值的变量的名称,所以我们正在构造一个名为 var
类型 B
的变量,其值为 A(20)
.
最令人头疼的解析问题是语法问题,而不是语义问题。在语法上,A(test)
归结为 identifier : OPEN_PAREN : identifier : CLOSE_PAREN
。在上下文中,这是不明确的,因为第二个标识符可能是变量名或类型名。编译器必须选择一种方式来解释这个标记序列,而且没有一个是不正确的。
相比之下,A(20)
归结为 identifier : OPEN_PAREN : integer_literal : CLOSE_PAREN
。整数文字不能解释为标识符,因此无法将其解释为类型名。因此,它必须被解析为一个表达式,该表达式初始化一个 A
.