12 ms·
> Where C++ gives you many slightly different takes on the same concept (e.g. unique_ptr, shared_ptr and raw pointers), C gives you one way to go and that one h
by maleldil 5y ago
> Where C++ gives you many slightly different takes on the same concept (e.g. unique_ptr, shared_ptr and raw pointers), C gives you one way to go and that one has a conveniently compact notation (such as float).
You use unique_ptr and shared_ptr because float is unsafe. If you don't care about the safety that smart pointers provide, you can use float* in C++ too.
> ticking with the example of matrix math, it is baffling how C code is often more compact and readable than C++ code. A matrix declaration would be float matrix[4][4]; [...] Of course, you could take the same approach in C++ but then you are not really using C++. The example from above in C could be simply: float* top = matrix;
But that's not that same thing, is it? I fail to see how you're actually getting the top 3 rows there; you're just assigning a pointer. Again, you're making your code less safe and expressive by using no abstraction at all.
And please, how is `matrix_add(matrix_mul(A, B), c)` more compact and readable than `A*B + c`? And this is being kind to the C version.
If the problem is with C++'s compilation times, then it's perfectly reasonable; this is one of the major problems of the language. But using unsafe constructs and then saying that they're better than C++'s safer alternatives is just comparing apples to oranges.
- jimbob45 5y agoI agree he used a trash example. I would offer include guards/pragma once as a slightly better example.
- badsectoracula 5y agoFWIW i've seen a lot of 3D codebases in C++ that avoid operator overloading and instead use something like `A.multiply(B).add(c)` to make more explicit what is going on. Some even break that into multiple calls instead of using a single expression.
- jolux 5y agoI fail to understand how that’s more explicit to be perfectly honest. If it’s hard to resolve where overloads are coming from then that’s a problem but otherwise it just seems more verbose for no benefit. Addition and multiplication are the operations in use here, why shouldn’t we use their operators to represent them?
- gravypod 5y agoIn situations where the output's shape changes based on the operation this can be helpful. auto accumulate = ...; auto a = ... auto b = ... auto result = a*b; for (int row = 0; row < a.rows) { accumulate += result[row] } This expression might be entirely valid when a and b are both 2x2 but then becomes incorrect when there's a different shape in b.
- CyberDildonics 5y agoDo you mean type instead of shape? I also don't know what you mean by incorrect. C will also create casts when using two different number types in a math operation.
- gravypod 5y agoFor matrix and quaternions multiplication does not output the same type as the input. For example: int a = 1; a + a = 2; (int) a * 2 = 2; (int) auto ma = matrix<2, 4>(); auto mb = matrix<4, 1>(); ma * a is matrix<2, 4> ma * ma is not possible ma * mb is matrix<2, 1> Compilers used to be very bad at telling you what was going on here if you, for example, changed `<2, 4>` to `<3, 4>` or something. g++ now handles it pretty well: https://hastebin.com/idemopikag https://hastebin.com/idemopikag
- CyberDildonics 5y agoYour original comment was about something being incorrect, now you are talking about error messages, but I don't think either has to do with operator overloading.
- duped 5y agoThere is more than one definition of a matrix or vector product and whichever one is most obvious can be contextual.
- humanrebar 5y ago
- qalmakka 5y agoThe confusion created by operator overloading is easily solved by tooling. The compiler always knows what a given operator resolves to, and environments like Visual Studio Code with the right plugins can handily highlight what you are actually calling. Also I think that like everything in C++ it's a matter of not abusing a given feature. It's still useful to have the ability to overload operators because it makes the intent behind certain operations much clearer. There's nothing worse than not being able to address an ArrayList in Java with the subscript operator. Nowadays I don't use operator overloading in C++ a lot, it's mostly `=`, `==`, `<=>`, `bool`, `*`, `->`.
- framerate 5y agoYou'll find a lot of SIMD code using the multiple calls approach as for far too long C++ compilers did daft things like transfer the SIMD registers back to the stack or refuse to inline when the expression got slightly interesting.
- maccard 5y agoThat's still better than matrix_add(c, matrix_mul(b, a)) though - you can't do A.mul(B).add(C) in C
- userbinator 5y ago"safety" is really overrated. The paranoia-fueled security industry has turned programming into some sort of weird authoritarian dystopia.
- gravypod 5y ago"I know my software just works" is really hubris. The fly-by-the-seat-of-our-pants game industry has cranked up programmers egos and made them ignore a wide range of tools and practices that have been proven time and time again to improve developer velocity and reduce defects.
- everyone 5y agoI'm a game dev and imo web-devs are the 'seat-of-our-pants' guys. In games we tend to use compiled and statically typed languages. They're pretty strict in what they allow and many errors are picked up by the IDE and/or prevent your code from even compiling. Whereas javascript.. Your code could be doing almost anything yet it will run just fine. Also, cus its not compiled the IDE for javascript is much much less helpful (eg. theres no "find all references") and much more permissive.
- vvanders 5y agoI think it depends on a lot on the studio and culture. I don't think I saw a single unit tests before I left gamedev(a few smoketests to make sure the game didn't crash but that was about it). I also rebuilt our audio streaming system over the course of 48 hours to use the texture streaming subsystem when we exceeded the 64 file handle limit on an certain platform. We needed to hit a date for a TGS demo and I can guarantee you that we had things which were even more YOLO for a fairly decently sized team/game.
- christophilus 5y agoTo be honest, the game industry is a good counterpoint to TDD zealotry. You can go quite far with adequate results without a single unit test.
- giomasce 5y agoThe problem is not even just safety. You can write safe C, if you are careful (and you need to be careful also for C++, smart pointers do not just magically make everything right). The point is that OP makes the point that C requires to write less code, and this doesn't even seem true: you have to remember, each time some non-trivial object goes out of scope, to call its destructor/deallocator, which results in a lot of code (which can at times hard to read, especially if you have not completely linear control flow). Looking at just the declaration is a small part of the issue.
- Ygg2 5y ago> You can write safe C, if you are careful You can also live forever, if you have right combination of genetics and environment.
- z0ltan 5y agoYou analogy makes no sense. By your measure, nothing is safe.
- ksaj 5y agoLike when someone says "Lisp is homoiconic," and that automagically creates a thread of people tripping over themselves to make the same points they do every time "Lisp" and "homoiconic" appear in the same sentence. There should be a list of these language snowball avalanches somewhere. They work every time.
- Ygg2 5y agoI assume Lisp homoiconicity is closer to fact than "You can write safe code in C". I mean it is possible. In the same way all molecules of air could bunch up in one corner of the room suffocating you. It's a possibility.
- skohan 5y agoIt depends. One approach to avoiding tricky memory management issues is to avoid memory management altogether. In the kind of applications where C is a good choice, you might consider strategies like allocating all the memory you need to work with besides small structs which fit on the stack when the program starts and then never deallocate. If you're worried about performance this is often a very good strategy.
- dasb 5y agoCan someone tell me what it means that "float is unsafe"? I'd never heard about that.
- bionade24 5y agoThe statement was made about a float pointer. Still float precision is a problem beginners run into, too. So maybe it'll will help one reading it somewhen. float a = 0.1f * 0.1f; assert((a - 0.01f) < 0.0001); <-- Works assert(a == 0.01f); <-- Will fail
- nly 5y agoThe * has been erased by HN's markup.
- maccard 5y agoIt's actually float* - which is a pointer to a float (hn's formatting can eat these sometimes) example: float* f = GetF(); // In a C world, you rely on the documentation to tell you how long f is valid for. SomeFunc(*f); // We _know_ this is safe. std::unique_ptr<float> f = GetF(); SomeFunc(*f.get());
- deleted 5y ago[deleted]
- bruce343434 5y agoMarkdown ate some of your asterisks
- socialdemocrat 5y agoPeople get blinded by features. At the end of the day, what influence your ability to write safe code is the human brain. You have to be able to reason about and understand the code effectively to discover and fix problems. Ironically C++ by adding a ton of features to make the language “safer” basically achieves the opposite. Complexity obscures how your code works and thus aids in hiding critical bugs. I have had so many cases with obscure bugs the 15 years I used C++ that simply would be impossible to reproduce in C. Does it mean I advocate C for safer coding? Not at all, but I think the advantage of C++ is grossly overstated. Languages such as Go are better examples for writing safe code. Why? Because they quite strong type safety and good memory semantics while not adding too high complexity to the language. Everything is far more explicit than in C++ which has too much “magic” and implicit behavior.
- deleted 5y ago[deleted]
- kaba0 5y agoC++ can introduce bugs by obscuring the flow of code, but it can also alleviate many instances by having proper abstraction power. It’s about balance. I would say both C and Go falls into the “most lines are readable, but the whole is not” camp, due to not enough abstraction. For smaller programs one can hold in memory it may be good, but it doesn’t scale.
- Koshkin 5y ago> you can use float* in C++ too But then why bother with C++ at all, right? > more compact and readable This: overloading of operators (and function) is one of the biggest draws of C++ (along with RAII and templates).