为什么CLS()在C++11中有不同的含义
VS2010部分支持C++11。我在VS2010 RTM中编译了下面的代码。我不明白为什么代码CLS被分析成不同的含义。在decltypeCLS obj1;行中;,CLS表示类对象实体。但在CLS obj2CLS行中;,CLS表示一个函数指针,它不带参数地重新运行CLS对象。这种行为是预期的吗?标准中有描述吗为什么CLS()在C++11中有不同的含义,c++,visual-c++,c++11,decltype,C++,Visual C++,C++11,Decltype,VS2010部分支持C++11。我在VS2010 RTM中编译了下面的代码。我不明白为什么代码CLS被分析成不同的含义。在decltypeCLS obj1;行中;,CLS表示类对象实体。但在CLS obj2CLS行中;,CLS表示一个函数指针,它不带参数地重新运行CLS对象。这种行为是预期的吗?标准中有描述吗 struct CLS { int mi; }; int _tmain(int argc, _TCHAR* argv[]) { decltype(CLS()) obj1;
struct CLS
{
int mi;
};
int _tmain(int argc, _TCHAR* argv[])
{
decltype(CLS()) obj1;
obj1.mi = 10;
CLS obj2(CLS());
obj2.mi = 10; // error C2228: left of '.mi' must have class/struct/union
return 0;
}
更新12/8/2011
根据C++11 7.1.6.2/1,括号中的预期字符串是一个表达式。编译器只需要检查字符串是否可以被解析为有效表达式。如果是,则代码格式正确。因此,对于代码“decltypeCLS obj1;”,CLS被视为表示对象定义的有效表达式
decltype-specifier:
decltype ( expression )
更新日期:2012年1月3日
Potatoswatter解释了CLS obj2CLS的原因;是对象定义以外的声明
任何可以被解释为表达式或声明的东西都是声明,不管它有多不寻常。CLS obj2 CLS;声明一个函数,其参数类型CLS是一个没有返回CLS的参数的函数,其返回类型是CLS。是否应为:是 它被称为 是否预期:是 它被称为 在decltype的参数中,需要一个表达式。将CLS解释为表达式的唯一方法是将其解析为CLS类型的默认构造对象 然而,在C++03中工作方式相同的CLS obj2CLS中,有两种可能的解析:一种作为函数声明,另一种作为对象定义。作为函数声明,外圆括号形成一个参数列表,内容应该通过提供类型和可选名称来指定一个参数或参数列表。在该解析中,CLS被解释为函数类型 另一个有效的解析是作为对象的定义。对于该解析,括号中当然必须有一个表达式或它们的列表,将CLS解释为CLS类型的默认构造对象
int f();
现在您会同意,这声明了一个不带参数并返回int的函数,对吗?但是它也可以被解析为int类型的默认初始化变量的定义
一条总是给出人们期望的结果的规则在最好的情况下是复杂的,但很可能是不可能的
请注意,在C++03中,避免自动变量使用auto的简单方法是在定义前加上auto:因为函数声明从不以auto开头,这将迫使编译器将其解释为变量定义。由于在C++11中删除了auto的旧含义,因此它不再适用于非自动变量,而且对于非自动变量,它也永远不会起作用。在decltype的参数中,需要一个表达式。将CLS解释为表达式的唯一方法是将其解析为CLS类型的默认构造对象
然而,在C++03中工作方式相同的CLS obj2CLS中,有两种可能的解析:一种作为函数声明,另一种作为对象定义。作为函数声明,外圆括号形成一个参数列表,内容应该通过提供类型和可选名称来指定一个参数或参数列表。在该解析中,CLS被解释为函数类型
另一个有效的解析是作为对象的定义。对于该解析,括号中当然必须有一个表达式或它们的列表,将CLS解释为CLS类型的默认构造对象
int f();
现在您会同意,这声明了一个不带参数并返回int的函数,对吗?但是它也可以被解析为int类型的默认初始化变量的定义
一条总是给出人们期望的结果的规则在最好的情况下是compl
是的,但很可能是不可能的
请注意,在C++03中,避免自动变量使用auto的简单方法是在定义前加上auto:因为函数声明从不以auto开头,这将迫使编译器将其解释为变量定义。由于在C++11中删除了auto的旧含义,因此它不再起作用,对于非自动变量,它无论如何也不会起作用。正如其他人所说,这是最令人烦恼的解析。任何可以被解释为表达式或声明的东西都是声明,不管它有多不寻常。CLS obj2 CLS;声明一个函数,该函数的参数类型CLS是一个没有返回CLS的参数的函数,其返回类型为CLS 比如说,
CLS obj2( CLS() ); // forward declaration
CLS obj2( CLS fun() ) { // definition
return fun(); // use unusual functional argument
}
CLS foo() { // define a function to use as unusual argument
return CLS();
}
int main() {
CLS obj2( CLS() ); // still a forward declaration, even in this context!
CLS x = obj2( foo );
}
解决方案是使用C++11的统一初始化:
或者干脆
CLS obj2{};
正如其他人所说,这是最令人烦恼的解析。任何可以被解释为表达式或声明的东西都是声明,不管它有多不寻常。CLS obj2 CLS;声明一个函数,该函数的参数类型CLS是一个没有返回CLS的参数的函数,其返回类型为CLS 比如说,
CLS obj2( CLS() ); // forward declaration
CLS obj2( CLS fun() ) { // definition
return fun(); // use unusual functional argument
}
CLS foo() { // define a function to use as unusual argument
return CLS();
}
int main() {
CLS obj2( CLS() ); // still a forward declaration, even in this context!
CLS x = obj2( foo );
}
解决方案是使用C++11的统一初始化:
或者干脆
CLS obj2{};
代码CLS obj3obj1;obj3.mi=10;可以成功编译。为什么选择CLS obj2CLS;被视为函数声明,但CLS obj3obj1;是否被视为对象定义?它们有相似的形式。为什么不在CLS obj2CLS中使用CLS;因为C++语法很复杂:请参阅这里:@杰夫瑞:因为Obj1是一个变量,CLS是一种类型。obj3.mi=10;可以成功编译。为什么选择CLS obj2CLS;被视为函数声明,但CLS obj3obj1;是否被视为对象定义?它们有相似的形式。为什么不在CLS obj2CLS中使用CLS;因为C++语法很复杂:这里请参见:杰夫瑞:因为Obj1是一个变量,CLS是一种类型。现在C++中有一条规则,如果某事物可以作为声明和定义来解析,它将被解析为声明。也就是说,在这种情况下,将使用第一种解释。->错误由于函数声明从不以auto开头,这将迫使编译器将其解释为变量定义。->错误但它也可以被解析为int.->error类型的默认初始化变量的定义。现在C++中有一个规则,如果某个事物既可以作为声明也可以作为定义解析,它将被解析为声明。也就是说,在这种情况下,将使用第一种解释。->错误由于函数声明从不以auto开头,这将迫使编译器将其解释为变量定义。->错误但它也可以被解析为int.->error类型的默认初始化变量的定义。请更正。任何可以解释为表达式或声明的内容都是声明。在约翰的评论中,他说这是错误的。我想再跟你确认一下,对吗?如果是,你能指出C++规则中定义了什么规则吗?我同意。C++ 11语法避免了这种混淆。@杰夫瑞:不,Celtsk的错误陈述是关于声明和定义之间的歧义。将定义更改为表达式将是Johannes正在寻找的更正。任何可以解释为表达式或声明的内容都是声明。在约翰的评论中,他说这是错误的。我想再跟你确认一下,对吗?如果是,你能指出C++规则中定义了什么规则吗?我同意。C++ 11语法避免了这种混淆。@杰夫瑞:不,Celtsk的错误陈述是关于声明和定义之间的歧义。将定义更改为表达式将是Johannes所寻求的更正。