5 ms·
You forgot option 3), which I use myself: Write in a high-performance language that also has high-level features, and write 90% of your code without concern for
by hellofunk 10y ago
You forgot option 3), which I use myself: Write in a high-performance language that also has high-level features, and write 90% of your code without concern for the language's cool optimization features.
That's what I do and it's great. I don't use move semantics or think about them, I avoid heavy templates, and I focus a lot of my work on the functional tools in C++ now and the more elegant ways of doing stuff at a high level. For when I need those extra optimizations, no need to change languages, I'm already there.
- ced 10y agoHaven't used C++ in a decade - how is the modern functional programming working out without a GC? Isn't object ownership tricky to untangle? I read your option 3 and nodded - I'm using Julia for much the same reasons. I didn't expect C++ to be the answer, but it's cool that it can work out.
- cjhanks 10y agoIf you are using Julia, then I will presume you are primarily working in some form of numerical computing. It is a very wide field, so it is difficult to say if object ownership will be tricky or not. If you are working with (b|m)illions of particles or entities which are capable of changing ownership, you will have a hard time in any language. Whether that's the C++ ownership being unclear or the garbage collector defragmenting your memory (just because you don't see the issue doesn't means it's gone in GC languages). That said, typically I find most algorithms have a computable upper-bound memory constraint and so you just pre-allocate a slab and then objects reference it. You will usually get better cache coherency and less wasted operations/sec. You're left with only a couple pointers you need to delete when you're done with the structure. As for `functional programming`, it depends on what you're looking for. C++ has two killer features for this, in my opinion; expression templates can seriously improve performance of functional composition (see Eigen3), and compile-time elision of type-dependent code branches (like a static if). Since I have learned to use `unique_ptr`, `shared_ptr`, `weak_ptr`, (`deferred_ptr`), and to prefer idiomatic accessors like `.at`, `.find`, `.insert` I cannot recall the last time Valgrind was angry at me. I think I end up writing `new` and `delete` maybe once a month(?). If I was designing widgets or applications with hard to define user interaction, I imagine I would have more complaints to share.
- ced 10y agoInteresting, thank you for the detailed answer. Expression templates do look very intriguing and powerful, I wonder what kind of application it enable. Julia has several cool performance-oriented constructs too: generated functions, loop fusion, JIT compilation (like your static if), and immutables (http://julialang.org/blog/2013/03/efficient-aggregates http://julialang.org/blog/2013/03/efficient-aggregates). It has a lot of potential, but then, so do other performance-oriented languages. It'll be interesting to do comparisons in a few years when the dust has settled a bit.
- srean 10y ago> Expression templates do look very intriguing and powerful, I wonder what kind of application it enable. Fast chain of operations on an array was one of the primary motivations. You can take a look at Blitz++, I believe it was the first library to push that idea. But ET is not limited to numerical operations on an array, you could do query optimization, optimization of string concatenation, essentially any application where deforestation of parse trees have the potential to make things faster.
- KKKKkkkk1 10y agoCuriously enough, linear algebra is the canonical application for expression templates, and yet if you ask a linear algebra expert, they will tell you that expression templates bring no benefits to 99% of linear algebra computations and make your code complex and bug prone. For examples of how expression templates can screw you up in unexpected ways, see: https://eigen.tuxfamily.org/dox/TopicLazyEvaluation.html https://eigen.tuxfamily.org/dox/TopicLazyEvaluation.html https://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html https://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenType... https://eigen.tuxfamily.org/dox/TopicPitfalls.html https://eigen.tuxfamily.org/dox/TopicPitfalls.html
- cjhanks 10y agoIt depends on the codebase you are working with. Prior to 'auto' it was difficult to impossible to annotate expressions (thus forcing evaluation on assignment). Many people still believe "more lines of code = more slow", they will have problems. Functional non-template boundaries are also slow... any time you force evaluation you will see slow down. My experience... sometimes I have to pass through multiple reference frames to get to the correct affine transformation. I have three options: manually derive the transform (only works for a finite number of well understood transformations), waste BLAS ops on transform concatenation, or let expression templates fold numerical operations to the solution (often with numerical precision benefits btw).
- cheez 10y agoYep. I use C++ and don't bother with optimization because it's fast enough on my slowest machines (5-6 years old).
- Iv 10y agoI use both C++ and C# a lot these days, and like both. I am more comfortable with C++ so memory management is usually not a problem, interestingly I find that it is in C# that it is sometimes annoying to wonder if the objects you manipulate are references or values, but you end up getting the gist of it after a bit of practice. The prevailing rule in C++ is to try to avoid using pointers when you can, you should rather use references. It is surprising the amount of cases when this is enough. A lot of people use smart pointers in C++, which implement reference counting transparently for a little overhead. shared_ptr was made official in C++11. It allows to make pointers on an object and delete it when all pointers were destroyed. I personally prefer to do without smart pointers and make objects ownership explicit: If I need to have long-lived objects I will put them in a structure/array/container and comment about it being the original owners. I would then do allocation/deallocation manually, which actually makes me more comfortable, as I prefer it to be explicit. But that is purely a matter of taste.
- int_19h 10y agoNot all smart pointers are reference counting - unique_ptr is not, and it has zero overhead compared to a raw pointer. Sometimes you just need to heap allocate, or, say, shove a bunch of objects of different derived types in a same container.
- shermanyo 10y agoHerb Sutter gave a really great talk on this: https://www.youtube.com/watch?v=JfmTagWcqoE https://www.youtube.com/watch?v=JfmTagWcqoE He has 3 guidelines: 1. Prefer scoped lifetimes by default (local members) 2. Else prefer unique_ptr and containers 3. Else consider shared_ptr His whole talk gives examples that show the flexibility of unique_ptr and how modern C++ can express ownership. See slide 5 here: https://github.com/CppCon/CppCon2016/blob/master/Presentations/Lifetime%20Safety%20By%20Default%20-%20Making%20Code%20Leak-Free%20by%20Construction/Lifetime%20Safety%20By%20Default%20-%20Making%20Code%20Leak-Free%20by%20Construction%20-%20Herb%20Sutter%20-%20CppCon%202016.pdf https://github.com/CppCon/CppCon2016/blob/master/Presentatio...
- deleted 10y ago[deleted]
- duneroadrunner 10y agoI agree, C++ is very versatile in terms of supporting both low-level and high-level coding styles, and the fine-grained interleaving of the two. There is indeed a ridiculous, and probably unnecessary, amount of complexity available in the language, but if you're writing new code there's no problem with sticking to a reasonable subset and ignoring the esoteric stuff. Of course you may not be able to avoid it if you have to deal with other people's code. But I find it notable that the concern is still productivity versus performance. In this day and age shouldn't security and correctness have attained at least equal priority? I mean we still live in a world where every single year, every major web browser has at least one new critical "remote code execution" vulnerability reported. I think one thing that's being missed wrt the advent of C++11 is that it is now practical, when appropriate, to write memory safe C++ code that can be compared apples-to-apples with other modern languages. And outperform them. Except for maybe Rust. Maybe. shameless plug for those interested in memory safe C++ programming: http://www.codeproject.com/Articles/1093894/How-To-Safely-Pass-Parameters-By-Reference-in-Cplu http://www.codeproject.com/Articles/1093894/How-To-Safely-Pa...