首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么CLS()在C++11中有不同的含义

为什么CLS()在C++11中有不同的含义
EN

Stack Overflow用户
提问于 2011-12-07 04:35:30
回答 3查看 340关注 0票数 1

VS2010部分支持C++11。我在VS2010 RTM中编译了下面的代码。我不明白为什么对代码CLS()进行不同意义的分析。在“decltype( CLS() obj1;”)行中,CLS()表示类对象实体。但是在"CLS obj2( CLS() )“行中,CLS ()表示一个函数指针,它不带参数地重新运行CLS对象。行为被期待了吗?它在标准中被描述过吗?

代码语言:javascript
复制
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;
}

更新2011年8月12日

按照C++11 7.1.6.2/1,括号中的预期字符串是表达式。编译器只需检查字符串是否可以解析为有效表达式。如果是,代码是格式良好的。因此,对于代码“decltype(CLS()obj1;”),"CLS()“被视为表示对象定义的有效表达式。

代码语言:javascript
复制
decltype-specifier:
    decltype ( expression )

更新1/3/2012

Potatoswatter解释了为什么"CLS obj2(CLS(CLS())“不是对象定义的声明。

任何可能被解释为表达式或声明的东西都是声明,不管它多么不寻常。CLS obj2( CLS() );声明一个函数,其参数类型CLS()是一个没有返回CLS参数的函数,其返回类型为CLS。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-01-01 20:18:53

正如其他人所说,这是最令人烦恼的问题。任何可能被解释为表达式或声明的东西都是声明,不管它多么不寻常。CLS obj2( CLS() );声明一个函数,其参数类型为CLS()是一个没有返回CLS的参数的函数,其返回类型为CLS。

例如,

代码语言:javascript
复制
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的统一初始化。

代码语言:javascript
复制
CLS obj2{ CLS() };

或者简单的

代码语言:javascript
复制
CLS obj2{};
票数 1
EN

Stack Overflow用户

发布于 2011-12-07 04:39:39

是的吗?是的

它被称为"most vexing parse“。

代码语言:javascript
复制
CLS obj2(CLS());  // function forward declaration.

CLS obj2  = CLS(); // Creates object zero initialized.
CLS obj2;          // Creates object default initialized.
票数 2
EN

Stack Overflow用户

发布于 2011-12-07 19:29:19

decltype的论点中,需要一个表达式。将CLS()解释为表达式的唯一方法是将其解析为CLS类型的默认构造对象。

然而,在CLS obj2(CLS()) ( BTW在C++03中的工作方式相同)中,有两个可能的解析:一个作为函数声明,另一个作为对象定义。作为函数声明,外括号形成一个参数列表,内容将通过提供类型和可选名称来指定参数(或它们的列表)。在该解析中,CLS()被解释为函数类型。

另一个有效的解析是作为对象的定义。当然,对于该解析,在括号中必须有一个表达式(或它们的列表),将CLS()解释为CLS类型的默认构造对象。

现在在C++中有一条规则,如果某物既可以被解析为声明,也可以被解析为定义,那么它将被解析为声明。也就是说,在这种情况下,将使用第一种解释。

当然,这就产生了一个问题,即为什么选择第一种解释,而我们显然希望在此作出第二种解释。答案是,否则它将破坏C的兼容性(在某些情况下甚至是我们的期望)。例如,查看以下行:

代码语言:javascript
复制
int f();

现在您会同意,这声明了一个不带参数并返回int的函数,对吗?但是它也可以被解析为int类型的默认初始化变量的定义。由于上面提到的规则,它确实声明了一个返回int的函数。

在最好的情况下,总是给出预期结果的规则是复杂的,但很可能是不可能的。

注意,在C++03中,避免使用自动变量的一个简单方法是在定义前面加上auto:因为函数声明从来不以auto开头,这将迫使编译器将其解释为变量定义。由于auto的旧含义在C++11中被移除,这不再有效(对于非自动变量,它也从未起作用)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8410433

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档