11 ms·
Comparing Rust and C++
- shin_lao 12y agoIf I understood correctly, it is not possible to manually manage memory in Rust and do things like memory recycling or pools?
- seabee 12y agoNo, you can do that, and can do so safely (if you implemented the unsafe parts correctly, at least). For example, here's an arena allocator crate: http://doc.rust-lang.org/arena/ http://doc.rust-lang.org/arena/
- Animats 12y agoThere's a lot of unsafe code in there. The only allocation that really needs "unsafe" is "Vec", which is needed to have some way to convert raw storage into variable size arrays. Everything else could be built on top of "Vec". If you want the effect of an arena, you can have all the objects in the arena owned by a master object, and all the links within the arena weak, using "std::rc::Weak". This is a reasonable way to do a GUI or a web page, where there's heavy interlinking to neighboring graphical items, but those links don't indicate ownership. When the window or page closes, just drop the master object and the arena goes away. Yes, you spend more effort on deallocation. That's not where the time goes in a GUI. There's an argument for doing things that way, rather than sprinkling "unsafe" around the library. Make it solidly reliable first, then profile, then look into compiler optimizations to make it faster. (There's a macho mindset with some programmers. They think they don't need all that checking. They're wrong. Put those guys (it's usually males who have that attitude) on fixing obscure bugs or doing crash dump analysis for a while. They'll learn.)
- seabee 12y agoUgh. This is what is wrong with any discussion with performance; someone who only ever builds CRUD apps wades into the conversation spouting junior level truisms and raises the noise floor for those of us who have done steps 1 thru 3. This isn't Stack Overflow, you aren't educating beginners, and even then there is no need to come to the comments with an axe to grind. The compiler is not a magical fairy that optimises away the cost of memory allocation. You don't 'emulate an arena' with a vector of reference counted pointers, any more than you emulate a cheetah by painting spots on your body. Nobody uses an arena because they are lazy or hate destroying objects; you still pay the cost if your objects have the Drop trait. You use them because you have a bunch of fixed size allocations all with the same lifetime, and - after profiling - you need to exploit that fact. There will be unsafe code outside of Vec because you need to do four things: - allocate a chunk of memory (for non-relocatable objects) - construct objects in portions of the memory of that chunk - destruct objects in each chunk - deallocate the chunks of memory If Rust ever gets placement box we can do the whole thing safely, but IIRC there hasn't been a decision made nor any experimental implementation. Until then, if I need to turn off the safeties to get something done, I will - not to spite the condescending 'enlightened' who are above getting their hands dirty, but because if there is a business need and it can be done correctly with due diligence, it is not 'macho', it is the professional thing to do.
- simias 12y agoYou make good points but the ad hominem is really not necessary.
- seabee 12y agoIn the cold light of day I agree, but we're not robots; discussions have an emotional aspect to them and sometimes an emotional response needs to be expressed. You can't be that person who tells everyone "you're doing it wrong" unless you really know for sure they are, and even then you shouldn't make them feel bad about it. It's worse when the subject is a nascent project and people's ideas are forming out of discussions like this, but in general it has a chilling effect on the subject being discussed. In this particular example, we need to know the deficiencies of Rust's allocation model, and there is much to be gained by discussing them and finding a workable solution. Shutting down the discussion with 'use the safety tools you already have or you're a foolish brogrammer' is not acceptable.
- Animats 12y agoRust is a new language. Its designers are close to solving the problems they set out to solve, but they haven't fully succeeded yet. Heavy use of "unsafe" indicates that there are things you can't properly express in the language, or can only express inefficiently. It's worthwhile to separate the two. If you can't do it at all, there's a problem with expressiveness. If you can't do it fast, there's a problem with performance. It's useful to try to do things without using "unsafe" to cheat the system. Then you find out what the language needs to do faster. That's a trouble spot to be identified. There may be an optimization which leads to a safe and fast solution. Or there may be a way to make something checkable so that it's not necessary to do something unsafe.
- Ygg2 12y agoThere are certain classes of behavior that are safe but compiler flags them as problematic. To get around this restriction you use unsafe block or function.
- EpicEng 12y ago>No, you can do that, and can do so safely (if you implemented the unsafe parts correctly, at least). That is equally true of C++; you're completely safe as long as you don't make any mistakes.
- seabee 12y agoThe entire C++ language is an unsafe block. I think you're trying to be funny, but you missed the point. A concrete example of safety is that Rust can tell you if you reference memory from an arena after the arena goes out of scope. C++ can not.
- adrusi 12y agoYou're not wrong. Rust's contribution is that it statically verifies safety as much as possible, and when not possible, at least isolates all code which could potentially be unsafe. The means that if the program segfaults or has a data race or other unsafe behaviour, the programmer need only focus on code marked as unsafe to fix it. In practice, most applications have hardly any unsafe code, delegating all of their unsafe behaviour to libraries that have presumably been thoroughly tested.
- Ygg2 12y agoIf by true you mean false then yes I agree. There is a world of difference between this block/function is unsafe rest is enforced by compiler and everything written is unsafe, lets download third party program to check.
- swah 12y agoAre those annotations like Java's? http://doc.rust-lang.org/src/arena/lib.rs.html#353-363 http://doc.rust-lang.org/src/arena/lib.rs.html#353-363 I wish languages would let you say the whole file/module is special - for example, inline all functions.
- Flow 12y agoNot sure about inlining, but if you put #![some_attribute(args)] at the top of a .rs file, it applies to the whole file.
- shmerl 12y agoRaw pointers is a bad example to compare to Rust. It's more like comparing C to it. If anything one should compare managed pointers like std::shared_ptr and etc, especially since the author mentions C++11.
- TillE 12y agoAlso failed to use std::thread and its related synchronization primitives. And nobody who's been writing C or C++ for more than five minutes would actually make that mistake with a switch statement (omitting breaks). On the contrary, its fall-through behavior is often very convenient.
- jzwinck 12y agoI missed a break in a switch a few weeks ago. I have been programming in C++ for more than a decade.
- iopq 12y agoThere have been actual real world examples of simple things like one line if statements and forgetting switches breaking code in production software and leading to VERY dangerous things. Especially in C/C++ code.
- andywood 12y agoI have to agree with you. It's never registered as a problem for me. I think of it like an ordinary kitchen knife. Yeah there's an off chance I might cut myself, but 99% of the time I'm just going to enjoy a steak.
- Ericson2314 12y agoOne thing important to keep in mind that unique and shared pointers are actually _much_ less common than borrowed pointers in Rust. I have little C++ experience, but I can borrowed pointers in Rust are used exactly like the unsafe pointers that would be used in the same situation in C. In other words borrowed pointers allow you to write the same code you would in C, but safer. [Other Rust features necessitate or strongly encourage different coding styles.] This leads me to conclude that C++ smart pointers either give you less ergonomics, or less safety, than Rust.
- claudius 12y agoIt 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.
- stinos 12y agoGood 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'.
- wfunction 12y agoYou really think auto and cbegin/cend make any difference here?
- wfunction 12y agoHow does Rust handle multiple object files and dynamic linking? It seems to me that pretty much all of these guarantees break down if the compiler can't see the source code for the whole program at once.
- adrusi 12y agoAll the information needed to make these guarantees is the type information of all visible items in a translation unit ("crate").
- wfunction 12y agoI'm skeptical. Did they really make the type information stored in the ABI that advanced? Storing that kind of information outside of name mangling is a nontrivial feat (i.e. they'd need to rewrite the linker) and there's not a whole lot of information you can pack into name mangling.
- wtetzner 12y agoI believe it's stored as the value of a special symbol in the object. I'm pretty sure I read about it somewhere, but I can't find the link now. Does anyone know where to read about how Rust handles this?
- tomjakubowski 12y agoThey aren't stored in the mangled names. Types and other metadata on items are encoded into a special metadata file that lives in the archive.
- adrusi 12y agoIt basically generates a header file from the source code and then stores it alongside the object data containing the type information of all public items.
- wfunction 12y ago
- sspiff 12y agoWhile I love what Rust is trying to achieve and hate the many, many issues C++ has, this reads like a blatant propaganda piece. It's not comparing C++ with Rust, or at least not fairly. It's just listing the problems of C++ that Rust is trying to solve. Someone well versed in C++ could easily write an article with the same title and list a dozen reasons why C++ is superior.
- iopq 12y agoIt's not meant to be fair. Rust is created as a successor of C++ to completely overtake it everywhere.
- sspiff 12y agoYes, but everyone knows that it won't do that, and anyone who doesn't have brain freeze from the Rust Kool Aid understands that in programming languages, it's never so clear cut. I realize that Rust was designed to address the issues with existing systems programming languages, but surely it has flaws, tradeoffs and small annoyances, like every other programming language. I really like Rust and see the value in what they are trying to achieve, but I'm realistic enough that it won't be perfect.
- steveklabnik 12y ago> surely it has flaws, tradeoffs and small annoyances, like every other programming language. Rust core team member here: it absolutely does. Rust is _far_ from perfect, as much as I love it. Anyone who tells you Rust has no flaws is lying.
- mholub 12y agoCan you describe in few words which flaws do you see in rust?
- iopq 12y agoOf course it does, but then it wouldn't be a comparison of C++ to Rust as much as a list of things Rust doesn't do well yet.
- frozenport 12y agoDoes UB enabling code optimization? The 'dangerous switch' might run faster if the compile deduces that only two of the possibilities are valid?
- halayli 12y agoOne of the main problems of C++ is that programmers treat it as C with classes because that's what it feels like at the surface. They think they know it because it feels like C and many decide not to learn its patterns and details. From the examples given, it's clear that the author is not very familiar with C++ and is also comparing Rust to C++98 which is not fair. C++11 is almost a new language.
- Matthias247 12y agoThese biased bashes against C++ that advertise rust get somewhere between boring and annoying recently. Yes, Rust has some interesting safety features that prevent some issues that you can run into with C++ (but not all). And yes, most of us will agree that header files suck and the rust approach here is nicer. That template error message are also PITA is also well known - but on the other hand templates are different (and more powerful) than generics. On the other hand there are still a few constructs that I'm using using often enough in C++ that have currently no sane representation in Rust and that are astonishingly never mentioned in these articles: - Everything that you use the friend keyword for. In Rust there is no way to access private data defined in other file (because that will automatically be another module which is also something I disagree with). - Most things related to inheritance and interfaces. Composition is not always a better solution and Rusts traits seem still more suited for compile-time polymorphism than to runtime polymorphism. As an example try to find the equivalent of a `shared_ptr<SomeThing> thing(new SomeThing()); shared_ptr<ISomeThing> iface = thing` in Rust. And yes, I want to be able to use both afterwards. - Enabling concurrency. Some people might disagree but I think Rust is currently mostly good at preventing multithreading issues - but not at providing good and easy ways to enable it. E.g. something like boost asio would be between hard to impossible to implement in Rust because the safety mechanisms disagree with callbacks that mutate state or Future objects (which are similar to callbacks). For some things using low-level primitives like channels (aka queues) and creating new threads might be fine, but there are also enough cases where you would prefer a simple singlethreaded eventloop. All in all I think there are still enough areas where I think Rust still is (unfortunatly) no real alternative for C++. And as long as that's the case I think writing such biased articles isn't fair.
- keeperofdakeys 12y agoJust on your last point, Rust does have the ability to do unsafe code (and many multi-threading primitives use these internally). The real question is, how can these be exposed to Rust in a way that plays nicely with other Rust code. There are things like RefCell, which enables multiple threads to hold a reference to an object, with run-time checking of borrows. Or there are also explicit mutex wrappers that can be used. You could use these with channels, closures, or a callback system. As Rust matures, we should see more of these kinds of features find themselves into the standard library.
- joelthelion 12y agoRust looks really promising. Unfortunately, the tooling just isn't there yet, it seems. Release a working plug-in for YouCompleteMe and I will switch overnight ☺
- steveklabnik 12y agoIt's true that Rust's tooling is lacking, but if you're just looking for autocomplete for vim, https://github.com/phildawes/racer#vim-integration https://github.com/phildawes/racer#vim-integration exists. I haven't tried it myself, but I hear good things.
- nly 12y agoComparing languages with constraints which were laid in bedrock 30 years apart is fairly uninteresting. C++ is constrained by its compatibility with C, and always will be. Even C++17, which will be the biggest shift in the language ever, won't change this. I see very little evidence that most programmers actually care about the advantages Rust the language, as specified today, brings. I'd contest that these days the biggest reason competing languages like Go, Rust, Python, PHP and Java often trump C++ is less to do with the language, and more to do with these languages having sizeable and fairly decent standard libraries. Programmers want to get shit done. The C++ standard library is tiny and has seen fairly paltry growth over the years, with only modest introductions in C++11 of things like regex and threads. If a set of filesystem, HTTP, networking, and serialization libraries were part of the standard, and well implemented, we may well see a different landscape.
- humanrebar 12y agoHTTP is welcome, but I'll take logging, JSON, XML, unit testing, and a database interaction layer before that. Most of those are types of "serialization", I guess, but I'll go ahead and be a little more specific. And a type-safe dependency injection framework wouldn't be the worst thing in the world either.
- nly 12y agoHTTP is a continued pain point for C++ I find. It falls in to an impossible valley of "too simple for anyone to have bothered writing a really good standalone library" and "too complex to write myself". I don't see anyone jumping at the chance to build a HTTP request state machine built on top of nothing but the standard library when the standard library has no standard solution for efficient asynchronous operations or task scheduling.
- humanrebar 12y agoI'm not saying it's not needed, but there's a huge chunk of the C++ world that doesn't do web development. The other things I mentioned are more generally useful. In particular, XML support probably needs to come before HTTP support. Not that I'd turn my nose up at standard HTTP support.
- sheeba37 12y agoHow do you compare two languages when you seem to be familiar with neither?
- kichu37 12y agoHow do you compare two languages when you seem to be familiar with neither?
- moomin 12y agoI'd actually much rather read the opposite article: things that C++ excels at that Rust falls down on. I'm not an expert, but I think there's still allocation use cases C++ is better at.
- humanrebar 12y agoOff the top of my head: * C++ has more robust compile-time meta-programming facilities, at least for the time being. * C++ can generally include C (well, C89) code as-is with no translation layer. Rust's FFI is pretty inoffensive, but it's more work than a #include * It's easier to do the really dangerous stuff if you have a good reason to. You can actually call push_back on a std::vector without invalidating your iterators if you're careful. I've never seen it used properly in production code, but it's possible. At any rate, it might be more awkward to write equivalent code in Rust. Then again, maybe a deque is better than a vector for this use case, in which case I suspect that Rust is capable of a more optimal solution than push_back or std::back_inserter.
- steveklabnik 12y agoC++ can also easily bind to libraries written in C++, while Rust cannot. (those libraries need to expose a C interface for Rust to be able to)
- humanrebar 12y agoThat's true, though I blame C++ for its lack of a standard ABI more than I would blame Rust. Not that that helps if you're just trying to get work done.
- kibwen 12y agoI've flagged this because not only is it an unfair characterization of C++, it's also using a version of Rust that is six months out of date. As a Rust fan, I don't think we need to resort to cheap shots. The language stands well enough on its own; misinformation and propaganda pieces won't get us anywhere.
- Dewie 12y agoIf anything, the Rust community seems more concerned with only showing the good sides of its community than it is with only showing the good sides of Rust. That of course has its social/"political" advantages.
- kibwen 12y agoI see this as a technical advantage, not a political one. I want the language to be legitimately great, which means that we need to encourage an atmosphere where people feel welcome to express informed and constructive criticism. Breathless praise is surely kind, but it doesn't really advance the conversation. In other words: I already know that the language is good; I want you to tell me how it could be better.
- towelguy 12y agoThe one thing I don't like about Rust is the implicit return. Looking at code, it's easier to spot a missing/extra "return" than a missing/extra ";".
- Dewie 12y agoIf you put an "extra" (unintended) semicolon on the last expression, the function will return Void/Unit: if this doesn't agree with the given type of the function, then there will be a compiler error. If you forget a semicolon, then the type of the function will become the type of the last expression, which will again make the compile complain. Are there other issues that you had in mind?