4 ms·
I didn't mean trying to rewrite code to change dynamically allocated objects to stack based ones. That sounds more like an optimization that a managed language
by HarHarVeryFunny 3y ago
I didn't mean trying to rewrite code to change dynamically allocated objects to stack based ones. That sounds more like an optimization that a managed language like C# might do.
C++'s unique_ptr and shared_ptr both have a get() method that will return you a raw pointer to the managed object, which can be a safe optimization within a function holding ownership to the object, as well as allowing you to use legacy functions on it that take raw pointer arguments.
I was thinking the C++ compiler could itself realize when it is safe to do so, save the raw pointer to a temp variable, and "rewrite" smart pointer accesses to use this temporary raw pointer. One could even imagine the compiler changing smart pointer function parameters to raw pointers in some circumstances.
- School-Cotton 3y agoThen I’m afraid I don’t know what your point is. Rust’s borrow-checker isn’t a replacement for shared/unique pointers in C++. It’s a replacement for raw pointers.
- HarHarVeryFunny 3y agoMy point was that overhead is one common objection to C++'s shared/unique pointers - everything is a method call - but that could be mitigated by the compiler itself doing the type of raw-pointer lowering, when safe, that the get() method permits. From other replies in this thread is seems that Rust's borrow-checker addresses the high level issues of object ownership and thread safety - it's not just a replacement for raw pointers (i.e. a smart pointer), which is exactly what C++' shared/unique pointers are.
- tialaramex 3y agoborrowck is a semantic check. So, it's not a replacement for some particular C++ feature per se, it's not a feature in the sense you mean at all, it's just that while C++ and Rust both have these same semantic rules in place, Rust checks them and C++ does not. When you as a programmer inevitably get something wrong and break the rules, in Rust your program won't compile, in C++ it just has some arbitrary misbehaviour, maybe you notice, maybe you don't, maybe it matters, maybe it seems benign... until 8:26 tomorrow morning when suddenly it blows up and makes your customer very angry. In C++ the result of breaking semantic rules (not just those checked by the borrowck, most of the semantic rules in the language) is IFNDR - your program is Ill Formed, No Diagnostic Required - your entire program has no particular meaning, there is no explanation for what it does, shrug. In Rust it doesn't compile. For people whose overriding mission is to get the code to compile, C++ is very attractive. Broken garbage? Meaningless nonsense? Not my problem it compiled so I went home. If you want to write software that works, that seems like you didn't do the hard part.
- HarHarVeryFunny 3y agoThat last paragraph destroys your whole argument. If you really believe that Google and FaceBook (etc, etc) hire morons who don't care if their code works, then you are not qualified to talk about programming languages.
- School-Cotton 3y agoNot sure about Google, but Meta has tons of C++ code because it was written before Rust became a viable alternative. And of course, rewriting those millions of lines of code would be too expensive now. But Rust now has a large amount of mindshare there and is being used a lot in new projects.
- School-Cotton 3y agoThe main overhead of using shared/unique ptr for everything where you could have used stack allocation is not the extra method call for get etc, it’s the extra heap allocation. Compilers can probably inline get, but they can’t change heap allocations to stack allocations in general.
- HarHarVeryFunny 3y agoIf you're declaring an object on the stack, then there is no reason to be using a pointer to refer to it. You could take the address of it and assign that to a raw pointer if you wanted to for some (perverse!) reason, but you'd never then assign that to a shared/unique_ptr since that implies ownership. T t1; // stack, reference as t1 T* t2 = new T(); // heap, raw pointer, reference as * t2 std::unique_ptr<T> t3 = std::make_unique<T>(); // heap, smart pointer, reference as * t3 T* pt = &t1; // Create a raw pointer to t1! Bad idea!
- School-Cotton 3y ago> If you're declaring an object on the stack, then there is no reason to be using a pointer to refer to it. Why not? What if you have some function f(T *) that you want to call? But anyway, we're not _just_ talking about stack allocations, but also extra levels of indirection on the heap. For example, vectors store their elements in a heap-allocated buffer directly. If they kept them all in shared pointers, there would be an extra level of indirection. This means e.g. vector::operator[] has to return a reference (which is basically the same thing as a pointer under the hood); it can't return shared_ptr or similar (because storing all its elements as shared pointers would make it way slower due to the extra allocations). In Rust, vector access is safe (due to the borrow checker), but in C++, it's not. vector<int> v {1, 2, 3}; int& x = v[0]; v.push_back(4); printf("%d\n"); This code is UB in C++. In Rust, it's impossible to write something like this. fn main() { let mut v = vec![1, 2, 3]; let x = &v[0]; v.push(4); println!("{x}"); } This code fails to compile.
- HarHarVeryFunny 3y ago
- projektfu 3y agoAs these are templates, processed statically, isn't this essentially happening already? https://godbolt.org/z/ennj65v9z https://godbolt.org/z/ennj65v9z