为什么编译器没有警告没有名称的定义? 下面的C++代码不做任何事情(使用GCC 4.4.3)-它不打印文本: struct MyStruct { MyStruct() { cout << "Hello" << endl; } }; void foo() { MyStruct (); }
因此,现在我有点困惑。我认为[由于编译器优化]省略了临时代码,因此您看不到对c-tor的调用 您的代码在语法上是完美的,因此编译器不需要给出警告 编辑[根据OP中的编辑] MyStruct a()为什么编译器没有警告没有名称的定义? 下面的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,在
上述内容被解析为函数
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();