以下C ++代码不执行任何操作(使用GCC 4.4.3) - 它不会打印文本:
struct MyStruct { MyStruct() { cout << "Hello" << endl; } };
void foo() {
MyStruct ();
}
我认为这不是那么明显......更不用说忘记给出变量名的危险了。是否有编译器选项/警告禁止编译此类代码或允许它背后隐藏的秘密?
编辑:对不起。以上版本MyStruct();
进行实际打印。未打印的版本是:
void bar() {
MyStruct a();
}
所以现在我有点困惑。
答案 0 :(得分:6)
这不是声明,因为在MyStruct ();
中,MyStruct
将成为 decl-specifier-seq 的一部分,并形成类型名称< / em>其中。然后()
只能是函数声明符。这需要指定 declarator-id ,在您的情况下不是。需要一种特殊的语法形式来允许这样的语法来声明构造函数。但是这样的语法异常不是在声明语句中进行的。
所以这个结构不能是一个声明。它被解析为一个表达式,用于指定创建类型为MyStruct
的临时函数的功能强制转换。
如果编译器没有打印 Hello ,则它不符合要求,或者您没有在程序中调用foo
。
您的编辑也没有指定没有名称的声明。它改为指定 具有名称的声明。它声明了一个名为a
的函数。编译器无法通过此方式表达其他内容。
MyStruct a();
它可以通过在以后发现代码中的错误(例如以下内容)中使用恢复规则来推断这一点
a.f();
如果你的代码中有这个试图调用成员函数并且“a”是一个函数,编译器可以检查MyStruct
是否包含成员f
,这样表达式是良好的。但是,如果你忘了放括号怎么办?假设适当声明的成员MyStruct
,以下内容对于返回f
的上述声明函数有效。
a().f();
实际上,编译器无法真正知道你的意思。
答案 1 :(得分:3)
您的代码中没有“无名声明”。您有一个完全有效的表达式 MyStruct()
。这不是一个宣言,再一次,它是一个表达陈述。如果它没有打印任何东西,它就是优化的效果:在C ++中,它通常被允许消除临时性,即使它们的构造函数/析构函数有副作用。 (虽然这个上下文实际上不允许这样的消除。你确定你真的执行了那个表达式语句吗?)
答案 2 :(得分:3)
MyStruct a();
声明一个函数a
,它不带参数并返回MyStruct
。
答案 3 :(得分:2)
我认为临时因[编译器优化]而被删除,因此你没有看到对c-tor的调用。
你的代码在语法上是完美的,因此编译器不需要发出警告[如此]。
编辑 [根据OP中的编辑]
MyStruct a();
以上解析为函数a
的声明返回MyStruct
对象并且不带参数。
答案 4 :(得分:1)
嗯,临时物品是完全合法的。所以没有理由在这里警告。