为什么编译器没有警告没有名称的定义?

时间:2010-10-01 17:20:55

标签: c++

以下C ++代码不执行任何操作(使用GCC 4.4.3) - 它不会打印文本:

struct MyStruct { MyStruct() { cout << "Hello" << endl; } };

void foo() {
  MyStruct ();
}

我认为这不是那么明显......更不用说忘记给出变量名的危险了。是否有编译器选项/警告禁止编译此类代码或允许它背后隐藏的秘密?

编辑:对不起。以上版本MyStruct();进行实际打印。未打印的版本是:

void bar() {
    MyStruct a();
}

所以现在我有点困惑。

5 个答案:

答案 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)

嗯,临时物品是完全合法的。所以没有理由在这里警告。