tipos raciocinios que para nuevos mayor los fuerza discursivos datos dar con argumentos argumento argumentar argumentacion argumenta c++ c++11 move-semantics order-of-evaluation

c++ - raciocinios - Mueve la semántica y el orden de evaluación de los argumentos.



que es la fuerza de los argumentos (2)

Consulte la sección 1.9:

Excepto donde se indique, las evaluaciones de los operandos de los operadores individuales y de las subexpresiones de las expresiones individuales no tienen secuencia.

y

Al llamar a una función (ya sea que la función esté o no en línea), cada cálculo de valor y efecto secundario asociado con cualquier expresión de argumento, o con la expresión de posfijo que designa la función llamada, se secuencia antes de la ejecución de cada expresión o declaración en el cuerpo del llamada función. [ Nota : los cálculos de valor y los efectos secundarios asociados con diferentes expresiones de argumentos no tienen secuencia. - nota final ]

Creo que el problema es que no está muy claro si la inicialización de los parámetros se considera un efecto secundario asociado con las expresiones de argumento. Sin embargo, parece estar respaldado por la sección 5.2.2:

La inicialización y destrucción de cada parámetro se produce dentro del contexto de la función de llamada.

Y también hay una nota en el mismo párrafo que lo hace un poco más claro:

Cuando se llama a una función, cada parámetro (8.3.5) se inicializará (8.5, 12.8, 12.1) con su argumento correspondiente. [ Nota : dichas inicializaciones se secuencian de forma indeterminada entre sí (1.9) - nota final ]

Así que sí, la inicialización de los argumentos está secuenciada de forma indeterminada entre sí. Las inicializaciones pueden ocurrir en cualquiera de estas órdenes:

std::string message = make_what_string(id); std::string id = std::move( id ); std::string id = std::move( id ); std::string message = make_what_string(id);

En el segundo caso, make_what_string termina trabajando con una cadena movida desde.

Entonces, aunque std::move no mueve nada en realidad, lo importante es que el movimiento real tampoco tiene secuencia con respecto al otro argumento.

La definición del constructor de movimientos de basic_string(basic_string&& str) establece:

[...] str se deja en un estado válido con un valor no especificado.

Entonces no tienes un comportamiento indefinido, tienes un comportamiento no especificado.

Teniendo en cuenta lo siguiente:

std::string make_what_string( const std::string &id ); struct basic_foo { basic_foo( std::string message, std::string id ); }; struct foo : public basic_foo { foo::foo( std::string id) : basic_foo( make_what_string( id ), std::move( id ) ) // Is this valid? { } };

Debido a que el orden de evaluación de parámetros en C ++ no está especificado, me pregunto si la línea

basic_foo( make_what_string( id ), std::move( id ) )

En el código anterior es válido.

Sé que std::move no es más que un lanzamiento, pero ¿cuándo se ejecuta std :: string move ctor? Después de que todos los argumentos han sido evaluados y es hora de llamar al constructor base? ¿O se hace esto durante la evaluación de los parámetros? En otras palabras:

¿El compilador hace esto?

std::string &&tmp2 = std::move(id); std::string tmp1 = make_what_string(id); basic_foo(tmp1, tmp2);

que es valido O esto:

std::string tmp2 = std::move(id); std::string tmp1 = make_what_string(id); basic_foo(tmp1, tmp2);

que no es válido. Tenga en cuenta que en ambos casos el orden es el "inesperado".


No es realmente válido. El orden de evaluación de los argumentos de función no está especificado. En otras palabras, no sabes si el compilador elegirá esta secuencia:

tmp1 = make_what_string(id); tmp2 = std::move(id); basic_foo(tmp1, tmp2);

o este:

tmp1 = std::move(id); tmp2 = make_what_string(id); //id has already been moved from! basic_foo(tmp2, tmp1);