vsoftco
vsoftco

Reputation: 56577

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?

Upvotes: 8

Views: 1099

Answers (3)

Jarod42
Jarod42

Reputation: 218333

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.

Upvotes: 6

Quimby
Quimby

Reputation: 19223

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.

Upvotes: 2

eerorika
eerorika

Reputation: 238491

[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).

Upvotes: 4

Related Questions