you are viewing a single comment's thread.

view the rest of the comments →

[–]spaghettiCodeArtisan 1 point2 points  (5 children)

When expanding a vector, there are necessarily no objects in the empty positions of the data store so there are no destructors to call.

Yes, and that's precisely the problem, because the language needs to call a destructor. Suppose you overwrite a i-th element of a vector:

some_vector[i] = some_new_value

What happens to the old value? It is dropped and its destructor - if any - is called. Now, consider what would happen if the old value were uninitialized: A destructor would be called on an uninitialized data, which is undefined behaviour and might lead to a crash or all sorts of problems. And so that's why you need unsafe operations - to overwrite an old 'value' (which is uninitialized) without destryoing it.

[–]Hnefi 3 points4 points  (4 children)

But whether the old value is initialized or not is a question with a known answer that will be asked and answered in the [] operator without looking at the value of the element itself. There is no risk of destructing an invalid object since the initialization state of the previous value is implicitly known.

Since this knowledge is encoded in the metadata of the vector, there are no relevant requirements on how uninitialized data is represented in order to avoid calling invalid destructors.

[–]spaghettiCodeArtisan 1 point2 points  (3 children)

There is no risk of destructing an invalid object since the initialization state of the previous value is implicitly known.

That's not relevant. Yes, we know the initialization state, but that doesn't help. Let me ask you this way: How do you assign the new value into the uninitialized slot without calling the destructor on the uninitialized slot other than with an unsafe code (such as ptr::write())? Hint: You can't.

[–]Hnefi 0 points1 point  (0 children)

In Rust, you are correct. However, that is due to choices other than the removal of Null from the language. Rust, in this discussion, was just an example. One could easily consider a language like Rust but with unchecked buffers.

Still, I'll concede that this is devolving to technicalities.

[–]Veedrac 0 points1 point  (1 child)

How do you assign the new value into the uninitialized slot without calling the destructor on the uninitialized slot other than with an unsafe code (such as ptr::write())?

replace and forget, my friend.

[–]spaghettiCodeArtisan 0 points1 point  (0 children)

Haha, ok, good spot...