Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I resize a vector that was moved from?

I have some code in which I want to make absolutely sure that a moved-from std::vector will not leave secret data around (think about crypto key management). In my class' move constructor, I do something like:

X(X&& rhs): secret_vector{std::move(rhs.secret_vector)}{
    rhs.secret_vector.resize(N);
    safe_zero(rhs.secret_vector); // zero out all elements
    rhs.secret_vector.resize(0);
}

As you can see, I re-use the secret vector after moving from it. I looked at

Reusing a moved container?

but it was not absolutely clear that I can do this (I did not understand what "pre-conditions" really are).

My question is: can I resize a moved-from std::vector, perform some operation on it, then resize it back to zero?

like image 301
vsoftco Avatar asked Mar 07 '19 23:03

vsoftco


3 Answers

My question is: can I resize a moved-from std::vector, perform some operation on it, then resize it back to zero?

A moved from object should be in unspecified but valid state.

So you have the right to resize it (no precondition required for that). safe_zero it, and clear it.

(I did not understand what "pre-conditions" really are).

There are state conditions that object should have to not invoke UB.

For example, operator[](std::size_t i) requires that i < size().

resize(), clear() doesn't have requirements.

like image 141
Jarod42 Avatar answered Oct 14 '22 22:10

Jarod42


[defns.valid] valid but unspecified state value of an object that is not specified except that the object’s invariants are met and operations on the object behave as specified for its type

[Example: If an object x of type std::vector is in a valid but unspecified state, x.empty() can be called unconditionally, and x.front() can be called only if x.empty() returns false. — end example]

std::vector::resize does not have any preconditions. No matter what valid state a vector is in, resizing it would not have undefined behaviour (disregarding UB caused by constructors of contained elements; but those are not called when the argument is 0).

like image 22
eerorika Avatar answered Oct 14 '22 23:10

eerorika


Yes. The object is in valid but in unspecified state as stated in the linked question. That means that you cannot assume anything about the content of std::vector. Calling size is safe but it might not return the same value as before the move. The state of the vector is valid, meaning there are no dangling pointers inside or anything and all member functions including resize will work just fine. Moreover calling resize is one of the few meaningful functions to call because it "respecifies" the vector's state.

like image 37
Quimby Avatar answered Oct 14 '22 22:10

Quimby