这个 C++ 程序有啥问题?
Posted
技术标签:
【中文标题】这个 C++ 程序有啥问题?【英文标题】:What's wrong with this C++ program?这个 C++ 程序有什么问题? 【发布时间】:2011-05-04 09:07:29 【问题描述】:当我编译这个程序时:
#include<iostream>
using namespace std;
std::cout<<"before main"<<endl;
int main()
...我从编译器中看到了这个错误:
错误:预期的构造函数, 析构函数,或之前的类型转换 '
请帮助我理解这意味着什么以及我的程序有什么问题?
【问题讨论】:
问题是为什么大多数 c++ 编译器都会给出如此糟糕的错误信息。 希望智能编译器能产生更好的错误。 好吧,在这种情况下要给出有意义的信息并不容易。甚至 clang 说:“错误:命名空间 'std' 中没有名为 'cout' 的类型”和operator<<
的“错误:预期的 unqualified-id”。
@Ugo:人类很容易阅读和看到错误,因为我们看到的上下文比编译器在错误点看到的要多。编译器只看到了错误点之前的内容(可能是错误之后的一两个标记,因为它试图确定错误)。因此,鉴于这一点以及对 C++ 语法的理解,错误变得更加明显。编译器看到 std::cout 并且现在正在寻找“构造函数、析构函数或类型转换”,因为这些是唯一可以生成有效声明或语句(因此也是有效程序)的下一个标记。
@Martin 我同意你的观点,并且我知道在编写编译器时可能会遇到的问题(真的)。但有时它只是让我难过。例如,我们必须等待 gcc4.6 才能“更清晰地诊断 |class|、|struct| 和 |union| 定义之后的丢失分号”... 结构在大约 40 年前出现在 C 中:'(.
【参考方案1】:
您看到该错误是因为您的
std::cout<<"before main"<<endl;
声明必须在您的 main()
函数(或其他函数)的范围内才能使该程序有效:
int main()
std::cout<<"before main"<<endl;
与您的具体问题无关,多提一点:因为您是using namespace std
,std::cout
上的显式std::
是多余的。
【讨论】:
从 main 返回一个整数是可选的。该标准规定在主函数的右大括号之前添加了一个隐式的return 0;
。这仅对main
有效,如果其签名指定了返回类型,则所有其他函数都必须返回。
但是如果在 main 之前有一个全局对象,那么在该全局对象的构造函数 cout wokrs..我不明白为什么它在 main 之前不起作用
@David Rodriguez - 同意,这就是为什么我说“应该返回”而不是“必须返回”。尽管它是可选的,但它仍然是一种很好的做法。
@abcd - 构造函数是一个函数,因此您的语句在那里有效。您不能做的是在源文件中间添加一条语句,完全靠它自己 - 它没有意义,并且永远不会被执行。请参阅@Nawaz 的答案,了解另一个声明在哪里有效的示例,而不是在函数内。
@jhasse 为了清楚起见,我猜。该标准规定 (3.6.1/5) 不明确地从 main 返回相当于return 0
,但根据我的经验,明确它永远不会有坏处。这个小程序在这里没有问题。【参考方案2】:
语句不能在函数外执行。
但是,如果您创建用于初始化全局变量的 表达式,那么从编译器不会给出任何错误或警告的意义上说,这将是可以的。
例如,下面的代码将打印你要打印的内容:
#include <iostream>
std::ostream &gout = std::cout<<"before main"<< std::endl;
int main()
输出:
before main
在线演示:http://www.ideone.com/Hz4qu
在这里,我做的事情几乎与本主题中所做的相同:
Is main() really start of a C++ program?
【讨论】:
事实上,制作一个实用程序来概括它是微不足道的:ideone.com/Iotcc 这是有问题的,因为它容易导致初始化顺序失败。无法保证gout
的初始化发生在在 std::cout
的初始化之后,因此您最终可能会在未初始化的cout
上调用operator<<
-> 未定义的行为
@David:你的意思是,如果我写int global_i = 100; int global_j = 2 * global_i
,那么不能保证global_i
会在global_j
之前初始化?
@Nawaz:如果两者在同一个翻译单元中,则保证顺序,如果在不同翻译单元中定义,则顺序未定义。 IE。 /* a.cpp */ int a = 10; int b = 2*a; /* b.cpp */ extern int a; int c = 2*a;
当main
启动时,a==10
和 b==20
,但 c
可能是 0
或 20
(0
因为 0
被初始化为 int
34 将被初始化为 int
@ 在任何其他初始化发生之前)
@Nawaz @David:我刚刚在我的博客上澄清了这一点,因为它很有趣。 gmannickg.com/?p=197【参考方案3】:
你不能写
std::cout<<"before main"<<endl;
在函数之外。
-- 编辑-- c++ 程序的单一入口点是 main 函数。在 main 函数执行之前唯一可能发生的就是静态/全局变量的初始化。
static int i = print_before_main_and_return_an_int();
【讨论】:
是的..从我的程序输出中可以明显看出...我想知道原因... 这很容易出现初始化顺序问题。不能保证cout
会在i
之前被初始化。
@abcd:嗯?你问你的程序有什么问题。错误是您将std::cout
行放在主要功能之前。您现在是否在问为什么这样做是错误的?【参考方案4】:
你必须在函数内定义行。
std::cout<<"before main"<<endl;
【讨论】:
【参考方案5】:以上答案是正确的,但只是补充。如果您已经拥有:
#include<iostream>
using namespace std;
您不必输入:
std::cout<<"before main"<<endl;
你可以输入:
cout<<"before main"<<endl;
因为你已经声明了你的 using namespace std;可以为您节省一点打字时间。 干杯!
【讨论】:
以上是关于这个 C++ 程序有啥问题?的主要内容,如果未能解决你的问题,请参考以下文章