4 ms·
It's way too easy to do something like this in c++: auto v = vector<int> { 1, 2, 3 }; auto &e = v[0]; // plan to use element later // ... v.pus
by idsout 9y ago
It's way too easy to do something like this in c++:
auto v = vector<int> { 1, 2, 3 };
auto &e = v[0]; // plan to use element later
// ...
v.push_back(v.size());
// ...
cout << e << "\n"; // boom
As a real example of this: suppose you're managing a vector of connected users. v is large enough to hold 64 user structs. e is a reference to the last user who produced an event. If a 65th user connects then the vector will need to be reallocated, thereby invalidating e.
Rust saves you here. The compiler will let you have a reference to the element if the vector is marked as immutable. If the vector is marked as mutable the compiler will yell at you and you'll need to store an index instead.
- fooker 9y ago>if the vector is marked as immutable So, mark it as const here and see the same effect?
- Eridrus 9y agoNot really the same thing. const will stop you from mutating the vector, but it won't stop you taking a reference to an element you get in a const vector. So, if you have a const reference, you can't make this mistake in it's entirety, but you can certainly make the mistake of keeping a reference to something you got through a const pointer. Also, marking as const is something you have to opt-in to, and there is still disagreement on the value of const.
- fooker 9y agoThat is a library design issue. You can certainly design a vector that is immutable by default and can only allow you to get references when immutable and push_back when mutable. That is the point of C++, things other languages do at a language level you can easily design as a library without paying a cost if you do not use it.
- idsout 9y agoWhat does cost mean here? Performance? You do not pay a performance cost for borrowing semantics in rust.
- Eridrus 9y agoThis still doesn't solve the problem because there is nothing stopping you from having both immutable & non-immutable references to the same data structure. And does not enforce that there are no references hanging around when you go from immutable to mutable. Which is precisely what Rust does.
- idsout 9y agoMarking it as const will not allow you to push_back. c++ has no problem letting you maintain a reference to an element in the vector while calling push_back.
- Koshkin 9y agoYes, vector is one of the most popular containers in C++ standard library and, at the same time, it is one of the most hideous. It, along with string, has such an insane potential for abuse that a programmer should always ask themselves whether it really is what they want.
- duneroadrunner 9y agoObligatory shameless SaferCPlusPlus[1] plug: It is now practical to eliminate the use of unsafe C/C++ elements (like pointers and iterators) by replacing them with safe, compatible substitutes. Using the SaferCPlusPlus library, your example code could become: #include "msemstdvector.h" // ... auto v = mse::mstd::vector<int> { 1, 2, 3 }; auto e = v.begin() + 0; // 'e' is a safe iterator here // ... v.push_back(v.size()); // ... cout << *e << "\n"; // no problem Not much different from your original code. Rust's policy of static enforcement of "exclusive mutable references" still might be preferable in many cases, but there is a practical option of using C++ in a safe(r) way. [1] https://github.com/duneroadrunner/SaferCPlusPlus https://github.com/duneroadrunner/SaferCPlusPlus