4 ms·
I'm not familiar with modern Java, but modern C++ has been advancing so fast that people are calling for a cool-down. The counter for "C++ is already too compl
by corysama 8y ago
I'm not familiar with modern Java, but modern C++ has been advancing so fast that people are calling for a cool-down. The counter for "C++ is already too complex" is that many of the new complexities are being put in place as simpler replacements for common boilerplate. For example:
Pointers, new, delete, malloc, free are all still there. But, you really don't need them any more. You can write large-scale programs using only objects, containers, iterators and unique_ptr (and shared_ptr if you can't clean up your design enough to avoid it). You basically get full memory management without garbage collection and while retaining RAII destructor capability.
"Optionally define this function based on these class properties. Else, define this alternative implementation" used to require a significant about of template boilerplate to pull off SFINAE. That has been cut down dramatically by if constexpr (). constexpr in general has been expanding to the point that someone wrote a compile-time ray tracer just to see if he could. Also, the oddly-named void_t makes it easy for if constexpr to "define this code if this statement will compile, else do this alternative". Between if constexpr, modules and a few more extensions (source_file/source_line?) there is a goal of eliminating 90%+ of the need for the preprocessor.
Functions with auto parameters, auto return types and containing some if constexpr can effectively be powerful templates without any <>.
Lambdas are obviously a shorthand for "functor" style class definitions. And, they can (auto)->auto.
range based for(auto &x:container) is much simpler than for(int i=0; i<n; i++) even though you are so familiar with for(;;) that you barely see it any more. But, even better, the standard algorithms spell out intent much better than a generic loop in 90% of cases.
Coroutines are already implemented in multiple compilers and are being standardized currently.
Variadic templates, parameter packs and tuples make wrapping arbitrary function signatures fast and easy.
nodiscard return types eliminate a whole class of errors. optional<T> return types are nice. The upcoming "zero-overhead deterministic exceptions" and expected<T,Error> are big improvements to error handling.
- raverbashing 8y agoThanks, that make a lot of sense. I'm favouriting this comment.
- tigershark 8y agoHow in the world would you get full memory management without garbage collection in c++?
- fsloth 8y agoThe author above is referring to reference counting. And no, there is nothing to capture circular refernce.
- tigershark 8y agoYes, I thought about that, but ARC is a form of garbage collection, so you can’t have automatic memory management in C++ without garbage collection, unless I’m missing something quite fundamental...
- corysama 8y agoOK. ok. "full" was an overstatement. You got me. The point is that you can write large programs without ever calling delete or free() and still not leak memory. True, it's not completely general nor impossible to screw up. You still need to be aware of issues like circular references. And, using shared_ptr would make lifetime as ambiguous as a Java reference. But, if you keep everything a DAG of containers and unique_ptrs, not only will your memory thank you, your coworkers will too.
- fsloth 8y ago"You basically get full memory management without garbage collection" No, you don't. Reference counting is not equivalent to garbage collection. Edit: Garbage collection has no problem collecting circular references if they are out of scope. Not so much for reference counted pointers. You will start leaking memory accidentally if you are not carefull - i.e. reference counting is not "automatic full memory management" - it will delete stuff once it's reference count goes to zero but it you will have to be careful not to come up with circular references that will leak.
- Jare 8y agoIf you can manage to not use shared_ptr (and, as the author says, you should try to) then you are not reference counting and you don't have circular references. As with Rust, the very few places where you may need such constructs can be carefully isolated, the other 99% of your code is "basically" safe from dangling pointers and memory leaks.
- bnolsen 8y agoDon't write circular references. That's shit design.
- hedora 8y agoBut you don’t get full memory management with garbage collection either. Take MVC GUI programming in Java, which I mention because the thread is about Java, and considerable effort was made by the core Java team at Sun to make this work well. If you use swing or awt and you call “longLivedThing.addEventListener(shortLivedThing)“ then you’ve written a memory leak. The two options: (1) create a directed a cyclic graph encoding desired object lifetimes, and make sure references obey it, or (2) use weak references to manually break the cycles. (1) is much easier in C++ because you can use rich reference types to get the compiler to automatically audit the lion’s share of your codebase. I don’t know of anyone that actually does (2) in Java because it makes it extremely difficult to reason about the actual runtime behavior of the program.