4 ms·
It's hard to know what really you're asking for, and how much you know about Rust. Rust itself has a bunch of guarantees. Rust's vector is guaranteed to work w
by Manishearth 9y ago
It's hard to know what really you're asking for, and how much you know about Rust.
Rust itself has a bunch of guarantees. Rust's vector is guaranteed to work well within that framework. So,
- No dangling pointers / UAF from stuff it gives you
- No iterator invalidation from iterators you get from it
- You can't push to it and invalidate references to its insides (this is really the iterator invalidation one over again)
- You can't use it in a way that will not be data race safe
These are all Rust guarantees; Vec just adheres to them. You can say that these guarantees are Vec guarantees too (which is why I'm saying "I'm not sure what you're asking for).
c++ std::vector does not have these guarantees because c++ does not have these guarantees. You can get some of these guarantees by restricting yourself to coding a certain way but they kinda fall apart when stuff gets complex in my experience.
Aside from that it's basically the same guarantees as std::vector, i.e. "will store stuff in contiguous space", "will allocate buffer with extra capacity as it grows" (this isn't actually a guarantee, but it's not going to change for either).
One thing Rust's vector guarantees that C++ doesn't is that Rust's vector will not store elements inline; anything (with nonzero size) you push into it will be heap allocated.
Rust's vector also never implicitly performs deep copies, but this isn't really a guarantee.
Rust also has a concept of zero sized types, which C++ does not, and Rust's vector deals with them in a certain way, however since C++ doesn't have these types you can't really compare.
It's possible C++ guarantees a drop order for where Rust's vector does not. I'm not sure.
- mehrdadn 9y ago> You can get some of these guarantees by restricting yourself to coding a certain way but they kinda fall apart when stuff gets complex in my experience. I would assume that in Rust it would fall apart just the same, except perhaps at compile-time rather than at run-time?
- Manishearth 9y ago> I would assume that in Rust it would fall apart just the same, except perhaps at compile-time rather than at run-time? No, because Rust gives you the tools to compartmentalize this stuff pretty well. Yes, if you write an unsound program it will fail to compile, but the language also guides you in the direction of not writing one, so huge complicated codebases written in 100% safe rust are possible and do compile. With C++ as complexity grows it's harder to keep stuff safe, in my experience. YMMV.
- saagarjha 9y ago> how much you know about Rust Very little, so please bear with me ;) For example, from the linked page: > Most fundamentally, Vec is and always will be a (pointer, capacity, length) triplet. No more, no less. Does C++ also provide this guarantee? > Vec will never perform a "small optimization" where elements are actually stored on the stack for two reasons: Does C++ do this? and from your response: > No iterator invalidation from iterators you get from it How are you guaranteeing this? C++ doesn't, so what is going on behind the scenes to make this work in Rust? As you can see, I don't know enough about C++ as I would like either…
- Manishearth 9y ago> Does C++ also provide this guarantee? I don't think it does. It might. > Does C++ do this? IIRC C++ is allowed to perform the optimization. I don't recall if any current implementations do. They might. Edit: I'm wrong, it's not, however std::string is allowed to. > How are you guaranteeing this? C++ doesn't, so what is going on behind the scenes to make this work in Rust? Because Rust has an entire system of ownership and borrowing which exists at compile time to ensure these things don't happen.
- pbsd 9y agoC++ is not allowed to do the small buffer optimization for std::vector<T>. You'll find a number of small_vector<T> classes from third parties, though. The reason is that std::swap(v1, v2) must never invalidate existing iterators and/or references to elements into either vector, which the optimization would clearly break. std::string is the type you may be thinking of, where the standard does make a special exception to enable the SSO.
- Manishearth 9y agoaha! good to know. Yeah, I knew string can do SSO, so I assumed std::vector was allowed to as well.
- saagarjha 9y agoWell, I must be misunderstanding how iterators work in Rust, then. AFAIK in C++ an iterator is a thin wrapper around a pointer in memory, and resizing the container can cause the underlying "base" array to move around to somewhere else if it's reallocated–thus, the invalidation of the old iterator. What is a Rust iterator doing in this case?
- smitherfield 9y ago>One thing Rust's vector guarantees that C++ doesn't is that Rust's vector will not store elements inline; anything (with nonzero size) you push into it will be heap allocated. I believe this is incorrect and small-vector optimization is in fact disallowed by the C++ standard. In any case, standard or not, no implementation is ever going to do SVO because it would require a branch on every access, making them incompatible with SIMD instructions. >Rust also has a concept of zero sized types, which C++ does not No, C++ allows this optimization too, it just requires that the "sizeof" operator always returns an integer >= 1.
- Matthias247 9y ago> One thing Rust's vector guarantees that C++ doesn't is that Rust's vector will not store elements inline; anything (with nonzero size) you push into it will be heap allocated. Does C++ really not guarantee this? If yes then I probably have written quite a bit of "broken" code, which assumes that element addresses stay constant during moves of the container. std::vector<A> vec1; // And initialize it A* a = &vec1[0]; auto vec2 = std::move(vec1); A* b = &vec2[0]; assert(a == b);