Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

It might be a good idea to compare C++ and Rust and not “C with Classes and no use of compiler options” and Rust. They do have a fair point about ugly template error messages, but the remaining issues are mostly moot: Freed memory issues can be avoided using std::unique_ptr and its siblings, lost pointers to local variables shouldn’t occur when using references instead of pointers, uninitialised variables are warned against when compiling with the (hopefully standard) -Wall -Werror, implicit copy constructors can either be deleted or this particular issue can be avoided by using a unique pointer (which has no copy constructor, hence the enclosing classes’ copy constructor is also deleted), I don’t quite get the issue with memory overlap, which is mostly an issue of a function receiving the wrong number set of arguments for the way it is written. The bit about broken iterators is actually nice, but in this case could be avoided by handing an external function two const_iterator which then cannot be changed. I don’t get the problems with "A dangerous switch" and "A broken semicolons", both seem sensible constructs and if you have bugs, you have bugs. Multithreading works as expected, except that using C++11 <thread> would probably have been nicer and one would have to explicitly make e.g. the lambda passed to std::thread mutable.

All in all, yes, Rust seems to be a nice language and in particular the template system looks somewhat more understandable, but please don’t write "Comparing Rust and C++" when you’re not actually using C++ but some weird mishmash of C and C++. If there are new, delete or pointer arguments in functions in your code, you’re most likely doing it wrong.



> Freed memory issues can be avoided using std::unique_ptr and its siblings

You can use a std::unique_ptr after it is assigned to something else. That's basically a use after free.

> lost pointers to local variables shouldn’t occur when using references instead of pointers

Lost references to heap variables happen all the time in C++ when the target is deallocated before the reference is accessed. It's the same problem and Rust fixes it the same way.

> I don’t get the problems with "A dangerous switch" and "A broken semicolons", both seem sensible constructs

Really? Then you're being naïve or obtuse. Both are common sources of bugs in C/C++. Accidental failure to handle all inputs (common when additional inputs are added after the handling code is written) and subtle typos with major consequences (see Apple's "goto fail" bug).

The purpose of Rust is to eliminate causes of careless and accidental errors by forcing you to do things the right way every time (rather than permitting lazy code).


Good reply; would be better without that small sentence after "really?", though :)


> You can use a std::unique_ptr after it is assigned to something else. That's basically a use after free.

While true, you can make it throw in such scenarios.

I wouldn't be surprised if the debug builds of modern C++ compilers wouldn't do it already.


Here is some example code showing the problem:

http://pastebin.com/6wu7bcrF

I compiled it using both:

  g++     -std=c++14 -Wall -Wextra -g test.cpp -o test
  clang++ -std=c++14 -Wall -Wextra -g test.cpp -o test
GCC v4.9.1 and Clang v3.5.0.

Under neither case did it supply any warnings at compile time. In both cases it segfaults when it hits the second std::cout whilst running.


Since that's undefined behavior anything (including and especially things worse than a segmentation fault) could happen.


-Weverything on clang is what you want


That's a useful option to know, thanks. However, it still didn't detect the problem being discussed.


Still, those are just two among many.


> Really? Then you're being naïve or obtuse. Both are common sources of bugs in C/C++. Accidental failure to handle all inputs (common when additional inputs are added after the handling code is written) and subtle typos with major consequences (see Apple's "goto fail" bug).

I don’t know, it seems reasonable to me to allow switch() not to handle all possible inputs and/or fall through. Requiring for() loops to always have a body also seems unnecessary, there are cases where everything fits nicely into the three standard elements.


Rust allows you to not handle all possible inputs (but you must be explicit about it). If you look at the page again, you'll see "_ => 3", which is the rust version of a default case. This means that rust can tell if you if you forgot to handle a certain case.

As for the other things you list, I'd mark these more as "short-cuts", than features. It may take more effort to create code without them, but it gives parsing and code-readability improvements. Obviously the rust devs have made their decision here.


> You can use a std::unique_ptr after it is assigned to something else. That's basically a use after free.

No, that's a null pointer dereference.


C++ is like a fairytale forest, where staying on the one safe path through the woods (unmarked, known only by whispered lore) will give you a reliable system, but where you are constantly tempted by easier-looking diversions at the end of which lurk grues.

And heaven help you if nobody has yet whispered to you the secret of the one safe path. Or if you consulted an older textbook, and the idiom it taught has a grue.


It's pretty well known that one should read Stroustrup's book and the Meyers books. If one were to learn in a vacuum, perhaps they would take a false path, but the community is in agreement on what the best learning resources are.

As cute as your comment is trying to be, most languages cannot be learned by blindly trying things out, one should actually read a few books, try to be a part of the community and so on.


There's no such thing as an agreement. Perhaps on the learning resources, but not about which features should be used, which I think it is a better interpretation of the parent's comment.

Take the C++ that's used on Chrome and compare to a Qt application. They'll be very different, and some features will be outright forbidden, depending on the codebase (for instance, Qt doesn't use copy constructors, or exceptions, and uses its own smart pointer classes). Not even templates, if you are using QObjects.

I know of noone that uses features such as RTTI.


You not knowing anybody who uses RTTI doesn't mean much. I know people who use it. Our coding standard at work is mostly based on Meyers and Alexandrescu's guidelines.

Chrome and Qt's standards and design choices are their business and do not mean there is no recommended way to do things.


What are the reference of the books you are talking about ? Is it this two ones : http://www.amazon.fr/Effective-Modern-Specific-Ways-Improve-...

http://www.amazon.fr/C-Programming-Language-4th-ebook/dp/B00...

Note that they are both quite expensive. I am a student and it is not nothing to pay for this books.


I am talking about Effective C++, More effective C++ and Effective STL by Meyers and The C++ programming language by Stroustrup.

Effective Modern C++ is about the new C++11 and C++14 standards. I am reading it now, looks good so far.

If you can get one thing, maybe Stroustrup's book would be the best choice, but make sure you get the latest edition which includes C++11. Note that amazon.fr has the kindle versions at significant discount (there's also a bundle of Meyers' first three books) if you are ok with their DRM.


I remember being a student and not having a big budget for books. Now I have a small apartment, and no space to put the books I have.

Abe Books ( http://www.abebooks.com/ ) provides a good place to look for used copies of books. A significant portion of the books in my library have stamps on the pages indicating that they were discarded from really nice institutions.

Of course there are always free-to-read blogs, but unfortunately, good C++ blogs are harder to find than other, newer language blogs.


> C++ is like a fairytale forest, where staying on the one safe path through the woods (unmarked, known only by whispered lore) will give you a reliable system, but where you are constantly tempted by easier-looking diversions at the end of which lurk grues.

This is the best description ever. May I use it?


Of course.


>uninitialised variables are warned against when compiling with the (hopefully standard) -Wall -Werror

Not with GCC:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=18501

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55873

Obviously it should warn you, but when one of the most popular C++ compilers has been failing to report uninitialised variables for 10 years then I think that the issue is worth raising. Clearly significant sections of the C++ community don't place a high value on the accuracy of these kinds of compiler warnings.


> Clearly significant sections of the C++ community don't place a high value on the accuracy of these kinds of compiler warnings.

This comes from the inherited C culture. After all lint was developed alongside the C compiler (in 1979).

How many C developers care to use static analysis?


In case anyone reading this is not familiar with it cppcheck is invaluable for finding such things.

http://cppcheck.sourceforge.net/


> The bit about broken iterators is actually nice, but in this case could be avoided by handing an external function two const_iterator which then cannot be changed.

No, I think you missed the point, which is iterator invalidation.

http://stackoverflow.com/questions/16904454/what-is-iterator....

It's important to understand that various container methods can cause iterators to point to something else (or even nothing!).

In the example given, push_back could cause all the contents of the vector to be reallocated at a new address to make room for the new element. Any iterators pointing to the old address, including the one used in the for loop, don't get updated in this process.

More details for the interested:

http://kera.name/articles/2011/06/iterator-invalidation-rule...

In contrast, Rust only lets you have more than one reference to an object (like a vector and an iterator) if all of them are immutable. So any container methods that would cause iterator invalidation wouldn't be available inside of a for loop.

EDIT: Re-reading, I realize you might have already understood iterator invalidation, so sorry for the re-explanation, but I'll leave it up there for those that haven't heard of it yet.

I will point out that:

1. This sort of for loop is idiomatic C++ code.

2. C++ compilers don't even warn you when you push_back while having active const_iterators to your vector. Rust does, which is the point of the example. This is a case where C++'s const (logically won't change) is inferior to a stronger immutability guarantee, which Rust provides.


>1. This sort of for loop is idiomatic C++ code.

No. This is C code. In C++ you write:

    std::vector<int> a = { 1, 2, 3 };
    std::cout << std::min_element(a.cbegin(), a.cend()) << std::endl;
You shouldn't be writing a lot of loops in C++. You should be using the algorithms as much as possible.


I'm aware of algorithms and espouse them, but you're not comparing apples to apples. The example is about mutating a collection while iterating over it:

  for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) {
      if (*it < 5)
          v.push_back(5-*it);
  }
...you could do that with std::for_each and a lambda, or maybe some creative use of std::back_inserter, but you'd still have iterator invalidation problems.

The right way to do it might be to use a while loop that uses std::find_if to find the next value to insert, but I'm not sure how you'd arrive at that solution without thinking about iterator invalidation in the first place.

...and the point is that Rust effectively says "you can't iterate over a mutable collection like that" while a less battle-scarred C++ developer might not even notice the problem before deploying to production.


Actually the simplest way to dix that code ils to write

it = v.push_back(5-*it);


Don't use "std::endl" unless you intend to flush the stream (doubtful in this case). It's not a replacement or synonym for "\n".


Good points. Also, first paragraph says C++11 (too be honest, C++11 mode) yet first example has std::vector< std::vector <int> >::const_iterator. Where's auto, cbegin/cend ?

In short: none of the C++ code written in the article resembles what a well-trained, well-behaved C++ programmer uses. And the same cannot be said of the Rust code, I think. On the other hand: maybe the whole point of the article is something like 'you don't have to be super well-trained in Rust yet won't shoot yourself in the foot'.


Yes, auto will save you:

    std::vector<bool> features(const Widget& w);
    
    ...

    auto highPriority = features(w)[5];
    processWidget(w, highPriority);  //whoops, undefined behavior
This is from Scott Meyers' new Effective Modern C++, in the chapter about why you should use 'auto'. Even the new 'safe' and 'convenient' features are loaded footguns.


You really think auto and cbegin/cend make any difference here?


Compilation-wise: of course not. As an illustration of what is wrong with the code: yes. auto means you don't have to spell out the complete iterator definition. cbegin\cend is just a matter of const-correctness.


C++ programmers generally know the iterator invalidation rules though.


> If there are new, delete or pointer arguments in functions in your code, you’re most likely doing it wrong.

Candidly, Modern C++ is an idiom adopted to work around the issues of raw memory management which Rust obviates out of the box.

What the author was writing was very standard introductory C++ taught in pretty much every C++ intro book I read in the early 2000s. That doesn't make it invalid C++, it makes it, "an older idiom".

To your more general point, C++ in the hands of an expert would clearly work better than presented here. I don't think that's an issue. The bigger question is, "Can C++ in the hands of a novice be as buggy as Rust in the hands of a novice".


> What the author was writing was very standard introductory C++ taught in pretty much every C++ intro book I read in the early 2000s. That doesn't make it invalid C++, it makes it, "an older idiom".

True. But that would suggest that we also consider Rust as it was taught in the early 2000s. I don’t think this would get us very far.

> The bigger question is, "Can C++ in the hands of a novice be as buggy as Rust in the hands of a novice".

Then it would be useful to firstly point out in the article that the matter of comparison is not the whole language but merely its usefulness to novices and to secondly consider the validity of such a comparison when deciding which language to use in a new project – if most people are novices for most of the time they use the language (e.g. in introductory numerical computing course), then clearly “novice friendliness” is a sensible measure, but otherwise it’s mostly a moot issue how hard the first two months are if you end up using it for the next ten years.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: