¿Reutilizar un contenedor movido?
¿Cuál es la forma correcta de reutilizar un contenedor movido?
std::vector<int> container;
container.push_back(1);
auto container2 = std::move(container);
// ver1: Do nothing
//container2.clear(); // ver2: "Reset"
container = std::vector<int>() // ver3: Reinitialize
container.push_back(2);
assert(container.size() == 1 && container.front() == 2);
Por lo que he leído en el borrador estándar de C++ 0x; ver3 parece ser la forma correcta, ya que un objeto después del movimiento está en una
"A menos que se especifique lo contrario, dichos objetos trasladados se colocarán en un estado válido pero no especificado".
Nunca he encontrado ningún caso en el que se "especifice lo contrario".
Aunque encuentro que la versión 3 es un poco indirecta y hubiera preferido la versión 1, aunque vec3 puede permitir alguna optimización adicional, pero por otro lado puede llevar fácilmente a errores.
¿Es correcta mi suposición?
§17.3.26 estado válido pero no especificado [defns.valid]
un estado de objeto que no se especifica excepto que se cumplen las invariantes del objeto y las operaciones en el objeto se comportan según lo especificado para su tipo
[ Ejemplo : si un objeto
x
de tipostd::vector<int>
está en un estado válido pero no especificado,x.empty()
se puede llamar incondicionalmente yx.front()
solo se puede llamar six.empty()
devuelvefalse
. - fin del ejemplo ]
Por tanto, el objeto está vivo. Puede realizar cualquier operación que no requiera una condición previa (a menos que verifique la condición previa primero).
clear
, por ejemplo, no tiene condiciones previas. Y devolverá el objeto a un estado conocido. Así que bórralo y úsalo normalmente.
Que el objeto esté en un estado válido, pero no especificado, básicamente significa que, si bien el estado exacto del objeto no está garantizado, es válido y, como tal, se garantiza que las funciones miembro (o funciones no miembro) funcionarán siempre que no dependan de ellas. en que el objeto tenga un cierto estado.
La clear()
función miembro no tiene condiciones previas sobre el estado del objeto (aparte de que sea válida, por supuesto) y, por lo tanto, se puede invocar en objetos movidos. Por otro lado, por ejemplo, front()
depende de que el contenedor no esté vacío y, por lo tanto, no se puede llamar, ya que no se garantiza que no esté vacío.
Por lo tanto, tanto la versión 2 como la versión 3 deberían estar bien.