来自Java视图的C ++:我一定错过了一些东西

时间:2010-09-01 10:27:57

标签: java c++ programming-languages

在此之前,让我首先澄清一下,由于我的知识有限,以下的想法完全是我个人的意见。我没有任何意图说C ++不酷。

我已经编程C ++一年了,我认为它确实有一些很酷的功能。然而,我觉得有点空虚和失望,因为我没有从C ++那里学到任何“改变思维”的东西,从一个碰巧以前学过Java(作为第一语言)的人的角度来看。

根据我读过的很多帖子,人们更喜欢C ++,因为它更快。对于像我这样以前没有编写时间关键应用程序的程序员,我还没有机会欣赏这一点。

到目前为止,我所学到的似乎都是关于语法的。这就是我们用Java编写类的方法,以及如何用C ++编写它。这是如何在Java中进行继承,以及在C ++中如何做等等。 (我知道,多重继承很酷,但对我而言,并不是一个改变思维的事情。我认为很酷的是能够回答为什么Java没有/不能支持多重继承,这应该是更通用的比单继承)。

对我来说,所有这些只是语法,到目前为止,我的思想在编写C ++之后似乎没有增长。我认为我的问题是用“Java-mind”编写C ++程序。正如许多人所说,我真正想要的是在学习一门新语言后改变我的思维方式。我还没有用我的C ++来解决这个问题。

我还可以编写几个小的Python程序。但是,我觉得害怕对它有更多的了解,再次,它只是学习一种新的语法,一种新的做事方式,只是不同而不知道原因。

我打算学习C来真正了解事情。我认为这将是一种非常“涉及”的语言。

让我知道你的想法,请给我一些建议。

PS:顺便说一下,C ++中有一个我想确认的特定问题。在C ++中,如果我是正确的,以下列方式编写是无效的:

    private A computeAndReturnA(){...} 

相反,请将其写为:

private void computeAndReturnA(A& a){...}

与第一种方式一样,复制返回的值(当我们指定b = compute ...时)并引入一些低效率? (在Java中,我认为第一种方式在意义上是明确的,在效率方面还可以,因为它通过引用传递内容)

8 个答案:

答案 0 :(得分:6)

总之,你完全错了。事实上,与Java相比,C ++提供了大量的自由。

例如,您可以在堆栈上分配类。 Java不提供这一点。您可以在编译时计算某些值。模板提供的功能远远超过泛型。您有能力将某事物作为参考或价值。在Java中,所有这些选择都会从您身上移除。就像在C ++中,您可以扩展多个类。您不必强制扩展Object。如果您愿意,确定性资源清理。我可以一个接一个地继续下去。

如果您所做的只是学习语法变体,那么以完全可以接受的方式使用C ++是完全可能的。但是,C ++提供了许多你在Java中看不到的东西。

简单的事实是,Java更像是C ++的一个子集,具有更大的标准库,加上反射和运行时代码生成,我想。

我更喜欢C ++,因为坦率地说,Java充满了任意限制。你知道为什么Java中没有“朋友”声明吗?因为詹姆斯·高斯林认为这违背了他的原则。大。棒极了。现在我需要将我的实现分成两个类,并且必须假装它是两个具有单独封装的实现,因为他在十年前认为这不是正确的事情。这就是我为什么Java糟透了的个人例子 - 你编写了James Gosling所说的应该如何,而不是你想要的方式,或者在很多情况下,你应该如何实际应该这样做。

另外,我看了你的PS。这就是为什么C ++有一个合适的编译器。实际情况是,几乎所有编译器都会将第一种形式转换为第二种形式,而其他一些您不想了解的令人费解的优化也是在幕后完成的。

答案 1 :(得分:2)

在这里学习C是你最好的选择 - 它会让你陷入困境,迫使使用你的Java思维模式,因此你可以更好,更轻松地过渡到C ++

答案 2 :(得分:2)

简单的事实是,用一种语言学习思考需要相当长的时间。最佳做法。这是一个漫长的过程,您首先要学习语法,并在开始时首先应用其他语言范例,以便找到自己的方法。

确实,如果你选择了一种与Java非常不同的语言 - 语法和范式 - wuse,你可能会更早地注意到这些差异,但不要低估C ++作为一种不同的范例。

C ++是一门学习起来非常复杂的语言,但它是一种可以给人一种容易学习的印象的语言,特别是因为语法与其他几种语言相似,但它还有更多。一个很大的主题是例如模板编程,使用模板是相当简单的,但是如果你看一下boost模板库,你会发现它非常复杂,建立这样一个库并不适合那些胆小的人。

学习语言不仅仅是学习语法,而是学习如何用这种语言进行思考。

也就是说,C ++是一种允许你自由和控制的语言,有时候会有太多的自由。

答案 3 :(得分:2)

绝对可以浏览www.boost.org,这将是一种改变思维方式的体验。

至于Post Scriptum中的问题:如果第一种形式涉及复制或不复制:它取决于并且取决于许多因素。

在当前的C ++中:

首先,如果编译器支持RVO,特别是当它也支持NRVO时,很可能不会发生高拷贝。然后它取决于函数的编写方式:

A computeAndReturnA()
{
   return A( x, y );  // no copy almost for sure
}

A computeAndReturnA()
{
   A a;
   a.f();
   a.g();
   return a;  // no copy if compiler implements NRVO
}

A computeAndReturnA()
{
   A a;
   while ( condition1 ) {
      a.f();
      if ( condition2 )
         return A();  // copy will take place
   }
   a.g();
   return a;  // copy will take place
}

那么这取决于你如何调用函数:

A a1 = computeAndReturnA();   // no copy if function body written appropriately,
                              // return value will be constructed directly in a1
A a2;
a2.foo();
a2 = computeAndReturnA();     // copy regardless of function body,
                              // return value can't directly be constructed in a2
                              // as a2 is already constructed

即将推出的C ++(2011年3月?):

与当前C ++相同的推理适用。但是,如果该推理表明将进行复制,并且如果类(此处为A)具有移动构造函数和移动赋值运算符,则将执行“移动”而不是“复制”。在理想情况下,移动将被省略,并且您将获得直接构造,但如果不是,您将在最坏的情况下移动,当然前提是返回的类是移动感知的。

我想你会发现这篇文章很有趣且内容丰富: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

答案 4 :(得分:2)

C ++比Java更通用,因为正如其他答案中所指出的那样,它是一种多范式语言,而Java只强调面向对象的编程(以及单一方式来执行OOP, )。

你当然可以在C ++中做很多事情,而你在Java中却无法想象。但是,对于拥有Java背景的人来说,我认为C ++是一个非常糟糕的学习工具,因为在Java中使用一些“删除”语句进行简单编码就太容易了。

如果你想要一些改变思维的经历,你应该学习一种主动强调另一种范式的语言,而不是一种让你选择你想要的范例的语言。

我建议使用Haskell(函数式编程),Erlang(一种不常见的并发方法),Factor(基于堆栈的编程),Prolog(逻辑编程),Common Lisp(CLOS&宏),Javascript(原型 - 基于OOP,即没有类)。

在我看来,这些将是改变思维的学习经历。我认为,即使它们确实支持Java没有的许多东西,Python和Ruby仍然非常接近Java模型;事实上,使用Java背景,很容易将它们视为同一模型上的另一个皮肤,语法略有不同,没有类型声明。

我的观点是,如果你想要打击你的思想,你必须学习一种新的范式。虽然在C ++等足够强大的语言上学习新范式当然是可能的,但通过学习一种迫使你使用这种范式的语言来学习新的范例将会容易得多。

有关一些改变思维的想法的简要概述,您可以观看these video lectures

答案 5 :(得分:1)

如果您正在尝试学习新语言以提高编程技能,那么可以尝试学习与C风格语法完全不同的内容。也许是Haskell,Scala或Erlang等功能语言之一。这将向您展示不同的编程语言,您将开始意识到Java / C ++ / C之间的细微差别。

否则,如果您的目标是解决特定问题,您可以选择一种语言。除非你有什么东西是性能关键的,否则坚持垃圾收集语言可能更容易。除非您计划进行iPhone开发,否则您应该切换到Objective-C

答案 6 :(得分:1)

关于你的问题:即将推出的C ++ 0x将具有移动语义,这应该加速“按值返回”到“按引用返回”的可比性能。这些不需要在客户端代码中进行更改,但可能需要在移动的类中实现其他构造函数。

关于你的咆哮:阅读Andrei Alexandrescu撰写的“现代C ++设计:应用的通用编程和设计模式”,并惊讶地发现C ++和Java(以及相应的思维模式)有多大差异。

答案 7 :(得分:1)

你可能不觉得C ++为你提供任何形式的糖果的原因是你来自Java背景,所有意图和目的都提供了一个非常直接和简单的C ++翻译。不是最好的C ++,但可能是一个可行的C ++实现......

... PS示例中不同成语的原因与引用无关(Java没有引用:Java有指向对象而不是引用;但C ++确实有引用和指针并且所有这一切都与Java内存分配相对便宜这一事实有关,而在C ++中则不然(因为在Java中,内存分配的成本在VM需要分配的所有内容上分摊 - 而在C ++中它不是 - 所以在Java中,VM确保仅根据需要分配内存。)

因此,在高效的C ++中,您会看到人们在紧密循环中避免了大量冗余的新调用,而在Java中,人们可以轻松地创建他们想要的临时对象。