这个 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&lt;&lt; 的“错误:预期的 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 stdstd::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&lt;&lt; -> 未定义的行为 @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==10b==20,但 c 可能是 0200 因为 0 被初始化为 int34 将被初始化为 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++ 程序有啥问题?的主要内容,如果未能解决你的问题,请参考以下文章

学习C++有啥用途?

C++ 类 - 我的程序有啥问题?

C++ std::atomic 在程序员级别有啥保证?

VBS和JAVA和C++,有啥区别,有啥差距

有啥方法可以使用在一个函数中定义的 const 变量可以被 C++ 中同一程序中的其他函数使用

C语言和C++有啥区别?