关于python:为什么C ++语法如此复杂?

Why is the C++ syntax so complicated?

我是编程新手,虽然我已经教自己Python大约一年了,我不久前学过C#。

本月我在大学开始了C ++编程课程,我只想问一下;"为什么C ++代码如此复杂?"

写"你好世界"。在Python中就像"打印'Hello world。'"一样简单,但在C ++中它是:

1
2
3
4
5
6
7
8
# include <iostream>
using namespace std;

int main ()
{
    cout <<"Hello world.";
    return 0;
}

我知道这可能是一个很好的理由但是,为什么......

  • ...你每次都要包括吗?你有没有需要它?
  • ...标准库的相同问题,何时不需要std :: *?
  • ......是一个功能的"主要"部分?你有没有打电话给主要功能?为什么是整数?为什么C ++需要一个main函数但Python不需要?
  • 你需要"std :: cout <<"吗?与Python相比,这不是那么漫长而复杂吗?
  • ......即使你永远不会使用它,你还需要返回0吗?

这可能是因为我正在学习这样的基本C ++,但到目前为止我所做的每个程序都是这样的,所以我必须一遍又一遍地重新输入相同的代码。这不是多余的吗?编译器本身无法输入此代码,因为它总是相同的(即afaik总是包含,std,int main,return 0)


C ++是一种更低级的语言,在没有解释器的上下文的情况下执行。因此,它有许多不同于Python的设计选择,因为C ++没有可依赖的环境来管理类型和内存等信息。 C ++可用于编写操作系统内核,除了程序本身之外,机器上没有代码运行,这意味着语言(某些库工具不适用于所谓的独立实现)必须是自包含的。这就是为什么C ++没有等同于Python的eval,也不是确定类的成员等的方法,也不是需要执行环境的其他功能(或者程序本身的大量开销而不是这样的环境)

对于您的个人问题:

  • 你每次都要包括吗?你有没有需要它?

#include 是将标头导入程序的指令。 包含标准输入/输出对象 - 特别是cout。如果您没有使用标准I / O对象(例如,您只使用文件I / O,或者您的程序使用GUI库,或者正在编写操作系统内核),则不需要

  • 同样的标准库问题,什么时候不需要std :: *?

std是包含所有标准库的命名空间。 using namespace std;有点像from std import *,而#include指令(在这方面)更像是准系统import std语句。 (实际上,机制是相当不同的,因为C ++不使用using namespace std;自动查找std中的对象; using-directive只将名称导入全局名称空间。)

我会在这里注意到,在C ++代码中,using-directives(using namespace)经常被不满,因为它们会导入很多名称并导致名称冲突。尽可能使用using-declarations(using std::cout;),因为限制了using-directive的范围(例如,限制为一个函数或一个源文件)。没有充分理由不要将using namespace放在标题中。

  • 功能的"主要"部分?你有没有打电话给主要功能?为什么是整数?为什么C ++需要一个main函数但Python不需要?

main是程序的入口点 - 执行开始的地方。在Python中,__main__模块用于相同的目的。 C ++不像Python那样执行定义函数之外的代码,因此它的入口点是函数而不是模块。

  • 你需要"std :: cout <<"吗?与Python相比,这不是那么漫长而复杂吗?

仅当您未通过using-directive(using namespace std;)或using-declaration(using std::cout)将cout名称导入全局命名空间时,才需要std::cout。在这方面,它再次非常类似于Python的import stdfrom std import *from std import cout之间的区别。

<<是标准流对象的重载运算符。 cout << value调用cout的函数输出value。 Python不需要这样的额外代码,因为print内置于该语言中;这对C ++来说没有意义,因为C ++甚至可能没有操作系统,更不用说I / O库了。

  • 即使你永远不会使用它,你还需要返回0吗?

编号main(并且没有其他功能)最后有一个隐含的return 0;main的返回值(或者,如果调用exit函数,则传递给它的值)作为退出代码传递回操作系统。 0表示程序已成功执行 - 未遇到错误等。如果遇到错误,则应返回非零值(或传递给exit)。


在帖子的最后回答你的问题,它可以用C ++的哲学概括:

你不支付你不使用的东西。

你并不总是需要使用stdin或stdout(Windows / GUI应用程序?),也不总是使用STL,你编写的所有东西都不一定使用标准main(winAPI)等。正如之前的海报所说,C ++比Python低。您将接触到更多细节,这可以让您更好地控制自己正在做的事情。


... do you have to include the
everytime? Do you ever not
need it?

如果您不打算在该模块中使用iostream,则不需要它。在较大的程序中,很少有模块直接执行任何实际IO,因此实际上很少需要使用iostream。

转过来的问题:在python中你需要在大多数非平凡的程序中导入sys和/或os。为什么?

... same question for the standard
library, when do you not need std::*?

您可以使用使用行,也可以使用std ::前缀。这非常类似于python的选择,你可以说"来自sys import *"或"import sys",然后不得不用"sys。"作为前缀。在python中你必须说"sys.stdout"。"std :: cout"真的更糟吗?

... is the"main" part a function? Do
you ever call the main function? Why
is it an integer? Why does C++ need to
have a main function but Python
doesn't?

是的,main是一个功能。通常你不会自己打电话给主。名称"main"保留用于程序的入口点。它返回一个整数,因为返回的值用作程序的状态代码。在Python中,如果要返回非零状态代码,可以使用sys.exit。

Python没有相同的约定,因为使用Python,您可以在不在函数中的模块中使用代码。加载模块时执行此代码。有趣的是,许多人认为将代码放在模块的顶层并且通过执行以下操作来创建主函数是不好的方式:

1
2
3
4
5
6
7
def main(argv):
  # program goes here

  return 0

if __name__ == '__main__':
  sys.exit(main(sys.argv))

此外,在Python中,您告诉解释器模块在运行时是"主"模块。例如:"python foo.py"。在C中,"main"模块(有效地)是具有称为main的函数的模块。 (如果有多个带有main函数的模块,那就是链接器错误。)

... do you need"std::cout <<"? Isn't that needlessly long and complicated compared to Python?

Python中的等价物实际上是"sys.stdout.write(...)"。 Python的print语句是一种特殊情况的简写。

也就是说,许多人确实认为使用IO变换操作符的iostreams惯例是一个坏主意。具有讽刺意味的是,Python似乎受到了这种语法的"启发"。如果你想使用print写入stdout以外的地方你可以说:

1
print >>file,"Hello"

... do you need to return 0 even when
you are never going to use it?

你不会使用它,但你的程序会。如前所述,您返回的值是程序的状态代码。

旁白:我确实觉得C ++过于复杂,但并不是因为你提到的任何一点。一旦你开始编写具有多个模块的非平凡程序并且不仅仅是写入stdout,你提到的所有差异都会消失(在某种意义上,你需要在Python中具有同样多的复杂性)。


所有这些都有很好的理由。 C ++是一种非常广泛的语言,用于从小型嵌入式系统到由100多名程序员构建的巨型应用程序。构建一个小程序的人在桌面上运行的用例绝不是唯一的。所以有时你正在构建库组件。在那种情况下没有main()。有时您正在使用没有标准库的小型系统。在那种情况下没有标准。有时你想构建一个与其他Unix文本工具一起工作的Unix工具,并用main()返回的int表示它的完成状态。

换句话说,你抱怨的事情是你的样板。但它们是重要的细节,与该语言的其他用户不同。


如果要将内容输出到控制台,请包含。由于打印"Hello world"涉及控制台输出,因此需要iostream

基本上,操作系统调用main函数。它通过传递给程序的命令行参数调用。它返回一个整数,因为程序必须向操作系统返回错误代码(这是确定最后一个命令是否成功的标准方法)。

如果你想要C风格,你总是可以使用printf("hello world");而不是std::cout <<"hello world";。编写它会更快,并允许您进行格式化输出。

您从main return 0表示程序已成功执行。

编译器不会自动包含所有标准库并使用namespace std,因为有时您的代码和库代码之间可能会发生名称冲突,而这些代码和库代码根本不需要。您并不总是需要所有库。同样,有时您使用的是不同的主程序(Windows开发时会想到自己的,不同的WinMain启动函数)。编译器也不会自动return 0,因为有时程序需要指示它未成功完成。


C ++相当复杂的原因之一是因为它旨在解决大型程序中出现的问题。在C ++创建为AT&amp; T时,他们最大的C程序大约有1000万行代码。在那种规模上,C不能很好地发挥作用。 C ++解决了使用这种程序时遇到的许多问题。

话虽如此,也可以回答原始问题:

  • 你需要include 。如果你有10.000个C ++文件,那么通常少于1000个,有时少于100个会产生用户可见的输出。
  • print"Hello, world"这样的语句假定存在默认输出,但很难进行泛化。 cout <<"Hello, world"表单使输出显式位于显式位置,但同样的形式也允许cerr <<"Goodbye, world"MyTmpFile <<"Starting phase #" << i
  • 标准库位于std::名称空间中。我的10.000个文件将在另外25个名称空间中。
  • main在许多方面都是一种奇怪的现象,即启动功能。


这让我想起了程序员的演变。现在展示的一些语言和技术有点陈旧,但你应该得到一般的想法。 :)


博德之门:

您并不总是需要。您唯一需要的是:

  • 一个main函数(或WinMain,如果您正在编写Win32应用程序)。
  • 变量,函数,运算符,语言结构(ifwhile等)。
  • 能够将库中的功能包含到您的程序中。
  • 其他一切都是特定于应用程序的。

    正如其他海报所说,main函数的返回值是错误代码1。如果main返回0,请高兴:一切正常!

    1当您编写与其他程序"通信"的程序时,这非常有用。程序可以"告诉"另一个程序是否正确执行的最简单方法是使用错误代码。


    正如人们所说,简单的答案是他们是不同的语言,目标不同。回答你的具体问题......

    ... do you have to include the everytime? Do you ever not need it?

    是iostreams的头文件之一,它是负责输入/输出的C ++标准库的一部分;在这种情况下,您需要它才能访问std::cout。如果您没有在源文件中执行I / O操作,则不需要包含它 - 例如,大多数包含类定义的文件可能不需要

    ... same question for the standard library, when do you not need std::*?

    std是包含标准库中类的命名空间的名称;它是为了避免名称冲突。 Python有包和模块来做到这一点。

    您可以使用using语句将来自另一个命名空间的项目添加到当前范围中,请参阅此FAQ条目以获取示例(以及解释为什么盲目地将所有std纳入范围内的原因!)。

    ... why is the"main" part a function? Do you ever call the main function? Why is it an integer? Why does C++ need to have a main function but Python doesn't?

    C ++中的可执行语句必须包含在函数中,main函数定义为执行开始的位置。在Python中,可执行语句可以放在文件的顶层,并定义执行。

    如果你愿意,你可以打电话给main() - 毕竟这只是一个功能 - 但是通常没有理由这样做。在幕后,大多数C ++实现会在运行时库完成一些启动内务管理后为您调用main()

    main()的返回值将返回给操作系统。这源于C和UNIX,其中应用程序需要提供1字节的退出状态代码,并从main()返回该值是一种明确的表达方式。

    ... why do you need"std::cout <<"? Isn't that needlessly long and complicated compared to Python?

    这只是一种设计差异。 iostreams是一个相当复杂的野兽,具有许多功能,其中一个副作用是语法对于简单的任务有时有点难看。

    ... why do you need to return 0 even when you are never going to use it?

    你确实使用它;这是作为程序退出状态返回给操作系统的值。


    Python是高级语言。 C ++是中级语言。