Могу ли я изменить размер вектора, который был перемещен? - PullRequest
4 голосов
/ 08 марта 2019

У меня есть код, в котором я хочу быть абсолютно уверенным, что перемещенный из std::vector не оставит секретные данные рядом (подумайте об управлении крипто-ключами).В конструкторе перемещения моего класса я делаю что-то вроде:

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);
}

Как вы можете видеть, я снова использую секретный вектор после перемещения из него.Я посмотрел на

Повторное использование перемещенного контейнера?

, но было не совсем ясно, что я могу сделать это (я не понимал, что на самом деле являются "предварительными условиями")).

Мой вопрос: можно ли изменить размер перемещенного из std :: vector, выполнить с ним некоторую операцию, а затем изменить его размер до нуля?

Ответы [ 3 ]

4 голосов
/ 08 марта 2019

Мой вопрос: могу ли я изменить размер перемещенного из std :: vector, выполнить с ним какую-то операцию, а затем изменить его размер до нуля?

Перемещенный объект должен находиться в неопределенном, но действительном состоянии.

Таким образом, вы имеете право изменить его размер (никаких предварительных условий для этого не требуется). safe_zero, и очистить его.

(я не понял, что такое «предварительные условия»).

Существуют состояния состояния, при которых объект не должен вызывать UB.

Например, operator[](std::size_t i) требует, чтобы i < size().

resize(), clear() не имеет требований.

4 голосов
/ 08 марта 2019

[defns.valid] допустимое, но неопределенное состояние значение объекта, которое не указано, за исключением того, что выполняются инварианты объекта и выполняются операции над объект ведет себя так, как указано для его типа

[Пример: если объект x типа std :: vector находится в допустимом, но неопределенном состоянии, x.empty () может быть вызывается безоговорочно, и x.front () может быть вызван, только если x.empty () возвращает false. - конец примера]

std::vector::resize не имеет никаких предварительных условий. Независимо от того, в каком состоянии находится вектор, изменение его размера не будет иметь неопределенного поведения (не считая UB, вызванного конструкторами содержащихся элементов; но они не вызываются, когда аргумент равен 0).

2 голосов
/ 08 марта 2019

Да.Объект находится в действительном, но в неопределенном состоянии, как указано в связанном вопросе.Это означает, что вы не можете предполагать что-либо о содержании std::vector.Вызов size безопасен, но может не возвращать того же значения, что и до переезда.Состояние вектора является действительным, то есть внутри нет никаких висячих указателей или чего-либо еще, и все функции-члены, включая resize, будут работать нормально.Более того, вызов resize - одна из немногих значимых функций, вызываемых из-за того, что она «переопределяет» состояние вектора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...