Hacker News new | ask | show | jobs
by hoodedmongoose 4065 days ago
This is really exciting, and clearly more powerful than what you get in C/C++. That being said:

>In a language like C++ there’s only once choice in this situation; that is to clone the vector.

What about a shared_ptr to the vector?

4 comments

A shared_ptr does not prevent iterator invalidation caused by reallocation, because the pointed-to vector is not locked, or in any other form stopped from being modified.

In Rust, when you have an immutable reference to a memory location, you know for certain that it won't be modified by distant code as long as you hold the reference. This guarantee also allows more compiler optimizations, because v[5] has the same value after a function call as before.

Thanks for the explanation, I missed that!
Doesn't help, because you don't necessarily know when the other shared pointer could push something to vector, potentially reallocating the internal array and thereby invalidating any references you had to the contents of the vector.
Ah okay - I didn't realize rust was guaranteeing that no one else would _modify_ the vector while an instance of that struct was around. That's pretty cool.
Rust follows multiple-readers or single-writer even in single-threaded situations. You can hold multiple immutable references to an object, or a single mutable one.

Initially this gets annoying, but as time passes one realizes how awesome this is. It prevents iterator invalidation (and vector-move-invalidation), for one (it's also necessary to get memory safety for our ADT enums since you can otherwise change the variant and invalidate a reference to its contents). In general you realize that in a large codebase, it's almost as bad as a multithreaded situation -- you don't know what objects are being modified by the methods being called and the code is too large to easily figure it out.

It's very cool. Rust guarantees that at any point in time there will only be one part of the code that can modify the contents of some data, and will fail to compile if it detects a situation where this is not the case.
Remember that this was an API, exposing the `&[Attributes]` to external consumers. I may not want to hold pointers to the insides, but a consumer of the API might.

Also, iterator invalidation.

Also, runtime overhead of shared_ptr.

(I added a footnote to the post to explain the issues with shared pointers)

Or scoped_ptr to transfer ownership.

There's certainly more than one choice, though.

Not really, and I say this as a fan of C++.

These things protect against one part of the problem - deletion of the vector, but not the other part - mutation of the vector, causing a new internal allocation, and leaving references to any elements of the previous vector invalid.

It's possible to make sure this isn't happening in C++ if a) your code base is small enough and b) you are careful, but the point of the article is that with Rust, you can make the changes and be confident that the compiler will fail if you do anything dangerous.

With C++, you can make the changes and through careful checking be reasonably confident everything works (perhaps only to find out later that you were wrong). It's very different from having the compiler verify that you are not doing something unsafe.

I couldn't have moved the vector, it was being used elsewhere.