为什么编译器没有警告没有名称的定义? 下面的C++代码不做任何事情(使用GCC 4.4.3)-它不打印文本: struct MyStruct { MyStruct() { cout << "Hello" << endl; } }; void foo() { MyStruct (); }

为什么编译器没有警告没有名称的定义? 下面的C++代码不做任何事情(使用GCC 4.4.3)-它不打印文本: struct MyStruct { MyStruct() { cout << "Hello" << endl; } }; void foo() { MyStruct (); },c++,C++,因此,现在我有点困惑。我认为[由于编译器优化]省略了临时代码,因此您看不到对c-tor的调用 您的代码在语法上是完美的,因此编译器不需要给出警告 编辑[根据OP中的编辑] MyStruct a() 上述内容被解析为函数a的声明,返回一个MyStruct对象,不带任何参数。好吧,临时对象完全是法律。所以这里没有理由发出警告。这不是一个声明,因为在MyStruct()中,MyStruct将是decl说明符seq的一部分,并在其中形成一个类型名。然后,()只能是函数声明器。这需要指定一个声明器id,在

因此,现在我有点困惑。

我认为[由于编译器优化]省略了临时代码,因此您看不到对c-tor的调用

您的代码在语法上是完美的,因此编译器不需要给出警告

编辑[根据OP中的编辑]

MyStruct a()


上述内容被解析为函数
a
的声明,返回一个
MyStruct
对象,不带任何参数。

好吧,临时对象完全是法律。所以这里没有理由发出警告。

这不是一个声明,因为在
MyStruct()中
MyStruct
将是decl说明符seq的一部分,并在其中形成一个类型名。然后,
()
只能是函数声明器。这需要指定一个声明器id,在您的情况下不是。需要一种特殊的语法形式来允许在声明构造函数时使用这种语法。但这种语法上的例外并没有出现在声明中

所以这个构造不能是一个声明。它被解析为一个表达式,该表达式指定一个函数强制转换,创建一个类型为
MyStruct
的临时类型

如果编译器没有打印Hello,则可能是不一致,或者您没有在程序中调用
foo


您的编辑也不会指定没有名称的声明。相反,它指定了一个具有名称的声明。它声明了一个名为
a
的函数。编译器不可能认为你的意思是别的

MyStruct a();
它可以通过在以后发现代码中的错误时使用恢复规则来推断这一点,例如

a.f();
如果您的代码中有这个函数来尝试调用一个成员函数,并且“a”是一个函数,那么编译器可以检查
MyStruct
是否包含一个成员
f
,以确保该表达式格式正确。但是如果你忘了放括号呢?假设有一个适当声明的成员
f
,以下内容对于返回
MyStruct
的上述声明函数有效

a().f();

因此,实际上,编译器无法真正了解您的意思。

您的代码中没有“没有名称的声明”。您有一个完全有效的表达式
MyStruct()
。它不是一个声明,再一次,它是一个表达式语句。如果它不打印任何东西,它的雾是优化的效果:在C++中,通常允许删除临时性的,即使它们的构造函数/析构函数有副作用。(虽然这个上下文并不允许这样的删除。你确定你真的执行了那个表达式语句吗?

MyStruct a()
声明了一个函数
a
,该函数不带任何参数并返回一个
MyStruct

,即使它正在打印一些东西,它也会对其进行优化吗?@JoshD:我不是编译器专家,但我认为这样的事情是不可能的。不过我不是很确定。如果我错了,请有人纠正我。为我打印:。也许g++需要某些标志,或者它认为
MyStruct()
是具有省略返回类型的函数的声明。或者你没有在任何地方调用
foo()
,我希望
MyStruct a()
是一个调用默认构造函数的定义,如'MyStruct a(1);`用一个参数调用构造函数。@Danvil其他人可能会认为它是一个返回
MyStruct
的工厂函数。那么
std::string getName()呢
?@Danvil:
MyStruct a(1)
实际上创建了一个对象
a
,但是
MyStruct a()
没有。请仔细阅读他的帖子。@Johannes:在全局或命名空间范围内,好吧…,但在函数内?@Danvil您可以声明在函数内的命名空间范围(和变量)中定义的函数。类似于
void f(){extern int A;string g();}
声明
A
g
,两者都是相同命名空间的成员。C语言是这样灵活的(C不知道<代码>类型())/>语法>,所以它没有理由担心歧义,C++在这里需要兼容。
a().f();