从 C 和 C++ 到 Ruby

很难用一个项目符号列表来描述你的 Ruby 代码与 C 或 C++ 代码相比会有哪些不同,因为它们之间的差异很大。其中一个原因是 Ruby 运行时为你做了很多事情。Ruby 似乎与 C 的“没有隐藏机制”原则相去甚远——Ruby 的核心目标是通过让运行时承担更多工作来简化人类的工作。除非你对代码进行性能分析以进行优化,否则在使用 Ruby 时,你无需关心“让编译器满意”。

也就是说,首先,你可以预期你的 Ruby 代码执行速度会比“等效”的 C 或 C++ 代码慢得多。与此同时,你会惊讶于 Ruby 程序的启动速度以及编写它所需的代码行数之少。Ruby 比 C++ 简单得多——它会把你宠坏。

Ruby 是动态类型的,而不是静态类型的——运行时在运行时尽可能多地做一些事情。例如,你不需要知道你的 Ruby 程序将“链接到”(即加载和使用)哪些模块,也不需要知道它将调用哪些方法。

令人高兴的是,Ruby 和 C 之间存在着健康的共生关系。Ruby 支持所谓的“扩展模块”。这些模块可以在你的 Ruby 程序中使用(从外部来看,它们看起来和行为就像任何其他 Ruby 模块一样),但它们是用 C 编写的。这样,你可以将 Ruby 软件中性能关键的部分隔离开来,并将它们熔炼成纯 C 代码。

当然,Ruby 本身是用 C 编写的。

与 C 的相似之处

与 C 一样,在 Ruby 中,…

  • 你可以根据自己的喜好进行过程式编程(但它在幕后仍然是面向对象的)。
  • 大多数运算符都是一样的(包括复合赋值运算符和位运算符)。不过,Ruby 没有 ++--
  • 你拥有 __FILE____LINE__
  • 你也可以拥有常量,尽管没有特殊的 const 关键字。常量性是通过命名约定来强制执行的——以大写字母开头的名称用于常量。
  • 字符串用双引号括起来。
  • 字符串是可变的。
  • 就像手册页一样,您可以在终端窗口中阅读大多数文档,尽管使用 ri 命令。
  • 您拥有相同类型的命令行调试器。

与 C++ 的相似之处

与 C++ 一样,在 Ruby 中,…

  • 您拥有大部分相同的运算符(甚至 ::)。<< 通常用于将元素追加到列表中。不过需要注意的是:在 Ruby 中,您永远不会使用 ->,它始终只是 .
  • publicprivateprotected 执行类似的任务。
  • 继承语法仍然只有一个字符,但它是 < 而不是 :
  • 您可以将代码放入“模块”中,类似于 C++ 中使用 namespace 的方式。
  • 异常以类似的方式工作,尽管关键字名称已更改以保护无辜者。

与 C 的区别

与 C 不同,在 Ruby 中,…

  • 您无需编译代码。您只需直接运行它。
  • 对象是强类型化的(并且变量名本身没有任何类型)。
  • 没有宏或预处理器。没有强制转换。没有指针(也没有指针运算)。没有类型定义、sizeof 或枚举。
  • 没有头文件。您只需在主源代码文件中定义函数(通常称为“方法”)和类。
  • 没有 #define。只需使用常量代替。
  • 所有变量都驻留在堆中。此外,您无需自己释放它们,垃圾收集器会处理这些问题。
  • 方法(即函数)的参数按值传递,其中值始终是对象引用。
  • 它是 require 'foo' 而不是 #include <foo>#include "foo"
  • 您不能降级到汇编。
  • 没有以分号结尾的行。
  • 对于 ifwhile 条件表达式,您无需使用括号。
  • 方法(即函数)调用的括号通常是可选的。
  • 通常您不需要使用花括号,只需使用 end 关键字结束多行结构(如 while 循环)。
  • do 关键字用于所谓的“块”。与 C 语言不同,没有“do 语句”。
  • “块”一词的含义不同。它用于与方法调用关联的代码块,以便方法体在执行时可以调用该块。
  • 没有变量声明。您只需在需要时动态地为新名称赋值。
  • 在测试真值时,只有 falsenil 评估为假值。其他所有内容都为真(包括 00.0"0")。
  • 没有 char - 它们只是 1 个字母的字符串。
  • 字符串不以空字节结尾。
  • 数组字面量用方括号而不是花括号括起来。
  • 当您向数组中添加更多元素时,数组会自动变大。
  • 如果您添加两个数组,您将获得一个新的更大的数组(当然,分配在堆上),而不是执行指针运算。
  • 通常情况下,所有内容都是表达式(也就是说,像 while 语句这样的东西实际上会评估为一个右值)。

与 C++ 的区别

与 C++ 不同,在 Ruby 中,…

  • 没有显式引用。也就是说,在 Ruby 中,每个变量都只是某个对象的自动解引用名称。
  • 对象是强类型但动态类型的。运行时在运行时发现该方法调用是否真正有效。
  • “构造函数”称为 initialize,而不是类名。
  • 所有方法始终是虚拟的。
  • “类”(静态)变量名始终以 @@ 开头(如 @@total_widgets)。
  • 您不能直接访问成员变量 - 对公共成员变量(在 Ruby 中称为属性)的所有访问都是通过方法进行的。
  • 它是 self 而不是 this
  • 一些方法以 '?' 或 '!' 结尾。它实际上是方法名的一部分。
  • 没有真正的多重继承。尽管 Ruby 有“mixin”(即您可以“继承”模块的所有实例方法)。
  • 有一些强制的案例约定(例如,类名以大写字母开头,变量名以小写字母开头)。
  • 方法调用的括号通常是可选的。
  • 您可以随时重新打开一个类并添加更多方法。
  • 不需要 C++ 模板(因为您可以将任何类型的对象分配给给定变量,并且类型在运行时确定)。也不需要强制转换。
  • 迭代的方式略有不同。在 Ruby 中,您不使用单独的迭代器对象(例如 vector<T>::const_iterator iter)。相反,您使用容器对象的迭代器方法(例如 each),该方法接受一个代码块,并将连续的元素传递给该代码块。
  • 只有两种容器类型:ArrayHash
  • 没有类型转换。不过,使用 Ruby,您可能会发现它们没有必要。
  • 多线程是内置的,但从 Ruby 1.8 开始,它们是“绿色线程”(仅在解释器中实现),而不是原生线程。
  • Ruby 自带一个单元测试库。