4 ms·
C++ features I miss in Java: * unsigned ints. Even Java's 8 bit byte is signed??! * operator overloading, mostly for math like matrices, vectors, complex numb
by Aardwolf 9y ago
C++ features I miss in Java:
* unsigned ints. Even Java's 8 bit byte is signed??!
* operator overloading, mostly for math like matrices, vectors, complex numbers
* containers of primitives
* ability to write a "swap" function (pass by reference)
* compiler that turns readable code into good assembly (no verbose code needed due to simpler code introducing stray stringstream objects and things like that, ...)
* destructors that reliably do something at end of scope
* no need to write typename twice to create an object (altho C++ std lib on the other hand requires writing container name twice for begin and end for sort and other algos and has horrificly inconvenient number to string conversions so that part I don't miss)
* ...
- minus7 9y ago> * operator overloading, mostly for math like matrices, vectors, complex numbers Kotlin has infix functions which help there without treading the dangerous territory of ambiguousness
- peoplewindow 9y agoKotlin also has operator overloading.
- tomjen3 9y agoI would agree with plenty of those, but they are mostly not needed for the work Kotlin targets (ie Android and Web dev).
- peoplewindow 9y agoSigned-only ints is really painful when working with binary formats, for sure. But the rules around unsigned vs signed ints in C/C++ are pretty painful. -fwrapv shouldn't exist. There is a library (GNU Trove) that provides specialised containers for primitives. It'd be nice if the language had them built in, but they're only quite rarely needed it seems. Normally there's some wrapper type involved. Java has scoped 'destruction' (called try-with-resources). An equivalent for 'auto' is coming to Java, though Kotlin has it already.
- Rusky 9y ago> Java has scoped 'destruction' (called try-with-resources). This is nicer than manually writing `finally` blocks, but it's nowhere near as nice as RAII-style destructors, which you can't accidentally leave out.
- pjmlp 9y agoSure you can, you just need to allocate them on the heap and forget about calling delete on them or not properly handle exceptions. Not everyone is writing C++ as they should.
- cesarb 9y ago> Java has scoped 'destruction' (called try-with-resources). Java's try-with-resources (and Kotlin's equivalent, .use()) are a start, but C++'s (and Rust's) ownership model is stronger. Java's model works fine when the resource doesn't have to escape the try block (and when you never forget to use the try block). But if you have a resource which might or might not escape the block (that is, its ownership might be to be passed to the caller, or to a separate long-living object), you have to do it manually, and if you're not very careful, you can have places where a stray exception leads to a resource leak. (Yes, this bit us recently at work, both the stray exception and the "another programmer didn't call .close()". Workaround for the later: finalize()...) In "modern" C++ style (which avoids manual new/delete most of the time, instead using unique_ptr and similar), ownership transfer is easier to make reliable: you can move the ownership into the return value or into another object, without leaving any gaps where a stray exception could leak the resource. And the default is to have ownership, so less chance of leaks due to forgetting to use a try block. Rust makes it even easier to avoid such leaks (outside of reference cycles, unsafe code using raw pointers, and the "leak it on purpose" mem::forget function).
- alkonaut 9y agoThis must literally have been the list used at Microsoft when making C#. Well most of them at least.
- andybak 9y agoI was wondering how many of these points are answered in C# (and in which version they were "fixed")
- alkonaut 9y ago> * unsigned ints. Even Java's 8 bit byte is signed??! > * operator overloading, mostly for math like matrices, vectors, complex numbers > * ability to write a "swap" function (pass by reference) These were in from the beginning > * containers of primitives Generics (in the proper sense, not the Java sense) came in C# 2.0/.NET 2.0 in 2006. With those you can make a List<T> and have it backed by an array of primitives that is consecutive in memory. That is, if you make a List<int> it's not a list of some boxed Integer type. > * compiler that turns readable code into good assembly (no verbose code needed due to simpler A bit subjective, but I'll argue that the JIT is getting better and is still nowhere near as good as an ahead-of-time compiler that can spend time optimizing the code. The JIT has to be FAST first and foremost since it produces its assembly WHILE the code is already running. > * destructors that reliably do something at end of scope There are no destructors and the only deterministic destruction is disposal (via IDisposable). Objects are not freed at that point however. You only use it to free resources, such as deterministically closing a file. The managed object representing the file will sit in memory until the next GC. The very bleeding edge version of C# yet to be finished will contain a lot more low level C++ like features which will make it more ergonommical to use stack memory (Google "Span<T>"). That will approach some of the C++ use cases. > no need to write typename twice to create an object Locals can be implicitly typed. So var pet = new Dog(); Is an allowed statement inside a method. This came in C#3 in 2007.
- scarface74 9y agoMy favorite feature of .Net is probably expressions trees. (https://blogs.msdn.microsoft.com/charlie/2008/01/31/expression-tree-basics/ https://blogs.msdn.microsoft.com/charlie/2008/01/31/expressi...). They have been around since 2008. A lot of non .Net people think that expression trees are just lambdas, but they are so much more powerful. If you have a method that has a signature: Find(Expression<Func<Employee,bool>> query) {…} And you call it by foo.Find(e => e.id == 5); That expression is treated as “data” not code. Meaning if your Find command is searching for Employees in SQL Server using Entity Framework, it will be translated to sql that runs on the server. If you’re using Mongo, it will be translated into MongoQuery. When you are unit testing you can mock it out, and process any given query against an in memory List<People>. If you are crazy enough, you can even move it out into a micro service and parse the expression tree yourself into a query object that you send to an API.
- maxxxxx 9y ago"* destructors that reliably do something at end of scope" That's almost a reason for going back to C++ (or PHP) for me. C# doesn't have it either but interestingly managed C++ does.
- sitharus 9y agoC# does have scoped destructors, but for GC reasons they use a separate syntax. `IDisposable` and the `using() { }` block do this. The downside is it's entirely opt-in, but it's well known and things like IoC containers can handle it.
- maxxxxx 9y agoPersonally I find the "using" syntax ugly especially with many variables and as you mention it relies on the caller to do the right thing. It would be better if the author of the class could control the behavior better.
- Too 9y agoTwo issues with using is that 1. Its restricted to functions, you cant have an IDisposable member without having to implement IDisposable yourself and there manually close the member. Just allowing an annotation on the variable would have made this so much more ergonomic. 2. The lack of ownership semantics when passing objects as function arguments makes it hard to reason about the program. There is no difference between temporary borrowed reference, ownership transfer and shared ownership so you never know if you are the one that should call close or if one of the functions did or will do in the future.
- gozur88 9y ago>operator overloading, mostly for math like matrices, vectors, complex numbers They took out operator overloading deliberately when they designed Java because in practice people mostly use it to obscure what's happening instead of making things more clear.
- wvenable 9y agoIn C++ operator overloading was used by the standard library to obscure everything. I can see why Java took the direction that it did. But, on the other hand, we've learned from those mistakes and pretty much any new language that has operating overloading it's used both appropriately and sparingly (C#, Python, etc). It's one of those things that as a developer you'd never use yourself but when you need them they're extremely handy. I'd loved doing matrix math in C++ -- I could translate complex mathematical expressions directly into code with almost no translation.
- gozur88 9y agoI agree it's a valuable feature if used in the right places. The problem is when you get a C++ job with an existing code base, particularly one which has been maintained by a lot of people over many years, invariably you're going to find operator overloading everywhere.