C++ from a Java-view: I must have missed a few things
Before anything, let me first clarify that the below thoughts are purely my personal opinions and due to my limited knowledge. I have no intention whatsoever to say that C++ is not cool.
I've been programming C++ for like a year and I think it really has some cool features. Nevertheless, I feel a bit empty and disappointed as I didn't really learn any "mind-changing" things from C++, from the standpoint of a person who happens to have previously learned Java (as the 1st language).
According to the many posts I've read, people prefer C++ as it's faster. To a programmer like me who haven't programmed time-critical applications before, I've yet to have a chance to appreciate this.
So far, what I've learned seems to me are all about syntaxes. This is how we write a class in Java, and here's how to write it in C++. This is how to do inheritance in Java and that's how to do in C++ and so on. (I know, multiple inheritance is cool, but to me, not a mind-changing thing. I think what's cool is to be able to answer why Java didn't/couldn't support multiple inheritance, which is supposed to be more general than single inheritance).
Somehow to me, all are just syntaxes and my mind hasn't seemed to grow after coding C++, so far. I think my problem it to write C++ programs with a "Java-mind". What I really want is, as many persons suggest, to change my ways of thinking after learning a new language. I've yet to get to that with my C++.
I can also write a couple of small Python programs. However, I feel afraid to learn more about it as to me, again, it would be just learning a new syntax, a new way of doing things that are just different, without knowing the reasons.
I plan to learn C to really get to know things. I think it would be a quite "involving" language.
Let me know what you think and please give me some advice.
PS: Btw, there is one specific question in C++ I want to confirm. In C++, writi开发者_JAVA技巧ng in the following way is not efficient, if I'm correct:
private A computeAndReturnA(){...}
Instead, write it as:
private void computeAndReturnA(A& a){...}
as in the first way, the returned values are copied (when we assign b = compute...) and introduce some inefficiencies? (In Java, I guess the 1st way is clear in meaning and okay in efficiency as it passes things by reference)
You're totally wrong, in short. The fact is that C++ offers a HUGE quantity of freedom compared to Java.
For example, you can allocate classes on the stack. Java doesn't offer that. You can compute certain values at compile-time. Templates offer far more power than generics. You have the power to make something a reference, or a value. In Java all of these choices are taken away from you. Like, in C++ you can extend more than one class. You aren't forced to extend Object. Deterministic resource clean up, if you want to. I could go on and on and on and on.
If all you do is learn the syntactic variants, then it's perfectly possible to use C++ in a somewhat acceptable fashion. However, C++ offers dozens of things that you would never see in Java.
The simple truth is that Java is more like a subset of C++ with a bigger standard library, plus reflection and run-time code generation, I guess.
I prefer C++ because Java, frankly, is full of arbitrary restrictions. Do you know why there's no "friend" statement in Java? Because James Gosling thought it went against his principles. Great. That's awesome. Now I need to split my implementation up into two classes and have to pretend that it's two implementations with separate encapsulation it because he thought ten years ago that it wasn't the right thing to do. That's my personal example of why Java sucks tremendously - you program how James Gosling says you should, not how you want to or, in plenty of cases, how you actually should.
Also, I looked at your PS. That's why C++ has a proper compiler. The reality is that virtually all compilers will turn the first form into the second for you, and some other mind-bending optimizations that you don't want to know about that are done behind the scenes.
Learning C is your best option here - It'll get you down to the bare bones, which forces to not use your Java mindset and as such you can have a nice, easier transition to C++.
The simple truth is that it takes quite some time to learn to think in a language e.g. best practices. It's a long process where you start with learning the syntax and probably in the beginning apply other language paradigms at first in order to find your way.
It's true that if you would have picked a language that is very different from Java - syntax-wise as well as paradigm-wuse you may noticed these differences earlier but don't underestimate C++ as a different paradigm.
C++ is a language that is very complicated to learn, however it's a language that can give an impression that it is easy to learn especially since the syntax is similar to several other languages however there is more to it than that. One big topic is for instance template programming, using a template is fairly straightforward however if you take a look at the boost template library you will that it can be quite complex and building such a library is not for the faint hearted.
Learning a language is just not about learning a syntax, its about learning how to think in that language.
That said, C++ is one of languages that allows you as much freedom and control as you want, sometimes too much freedom.
Definitely have a look at www.boost.org, that will be a mindset-changing experience.
As for the question in Post Scriptum: if the first form will involve copy or not: it depends, and depends on many factors.
In current C++:
The first is that if the compiler supports RVO and especially when it also supports NRVO, chances are high copy will not take place. Then it depends on how the function is written:
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
}
Then it depends on how you call the function:
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
In upcoming C++ (March 2011?):
The same reasoning as for current C++ applies. However, if that reasoning suggests that copy would be made, and if the class (A here) has move constructor and move assignment operator, then 'move' and not 'copy' will take place. In the ideal cases the move will be elided as well as you get direct construction, but if not you'll get move in the worst case, of course provided that the class being returned is move-aware.
I think you'll find this article interesting and informative: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
C++ is much more general than Java, in the sense that it is, as pointed in other answers, a multi-paradigm language, where as Java only stresses object-oriented programming (and a single way to do OOP, at that).
You can certainly do many things in C++ that you couldn't dream of in Java. However, for someone who has a Java background, I'd argue that C++ is a very bad learning vehicle, as it is way too easy to simply code in Java with a few "delete" statements here and there.
If you want some mind-changing experience, you should learn a language that actively stresses another paradigm, instead of a language that lets you choose whatever paradigm you want.
I would suggest one of Haskell (functional programming), Erlang (an uncommon approach to concurrency), Factor (stack-based programming), Prolog (logic programming), Common Lisp (CLOS & macros), Javascript (prototype-based OOP, i.e. without classes).
These would, in my opinion, be mind-changing learning experiences. I would argue that, even though they do support many things that Java doesn't, Python and Ruby are still pretty close to the Java model; indeed, with a Java background, it would be quite easy to see them as just another skin on the same model, with a slightly different syntax and no type declarations.
My point is, if you want to blow your mind, you have to learn a new paradigm. And while it is certainly possible to learn new paradigms on a sufficiently powerful language such as C++, it will be much easier to learn the new paradigm through learning a language that forces you to use that paradigm.
For a brief overview of some mind-changing ideas, you could watch these video lectures.
If you are trying to learn new languages to improve your programming skill, perhaps try and learn something that is quite different from the C style syntax. Perhaps one of the functional languages like Haskell, Scala or Erlang. That will show you how different programming languages can be and you'll start to realize the subtle differences between Java/C++/C as well.
Otherwise if you are aiming to solve a specific problem you can choose a language for that. Unless you have something thing is performance critical it is probably easier to stick to garbage collected languages. Unless you're planning on doing iPhone development, in which case you should switch to Objective-C
On your Question: The upcoming C++0x will have move semantics, which should speed up "return by value" to comparable performance of "return by reference". These dont need a change in client code, but one may need to implement an additional constructor in the moved classes.
About your Rant: Read "Modern C++ Design: Generic Programming and Design Patterns Applied" by Andrei Alexandrescu and by surprised how much C++ and Java (and the corresponding mindset) can differ.
The reason why you probably don't feel like C++ offers you any kind of candy for your mind is that you come from a Java background which to all intents and purposes offers a very direct and simple translation into C++. Not the best C++ to be sure, but a possible working C++ implementation...
... The reason for the different idiom in your PS example has nothing to do with references (which Java doesn't have: Java has pointers-to-objects but not references; but C++ does have references as well as pointers) and everything to do with the fact that in Java memory allocation is relatively cheap whereas in C++ it is not (because in Java the cost of memory allocation is amortized over everything the VM needs to allocate anyway -whereas in C++ it is not- so in Java the VM ensures that memory is only allocated as needed anyway).
So in efficient C++ you see that people avoid lot's of redundant new calls in a tight loop whereas in Java people can comfortably create temporary objects all they want.
精彩评论