Estoy aprendiendo C ++ en este momento y trato de evitar adquirir malos hábitos. Por lo que tengo entendido, clang-tidy contiene muchas "mejores prácticas" y trato de ceñirme a ellas lo mejor posible (aunque no necesariamente entiendo por qué se consideran buenas todavía), pero no estoy seguro de si entienda lo que se recomienda aquí.
Usé esta clase del tutorial:
class Creature
{
private:
std::string m_name;
public:
Creature(const std::string &name)
: m_name{name}
{
}
};
Esto lleva a una sugerencia de clang-tidy de que debería pasar por valor en lugar de referencia y uso std::move. Si lo hago, recibo la sugerencia de hacer nameuna referencia (para asegurarme de que no se copien todas las veces) y la advertencia que std::moveno tendrá ningún efecto porque namees constasí que debería eliminarla.
La única forma en que no recibo una advertencia es eliminando por constcompleto:
Creature(std::string name)
: m_name{std::move(name)}
{
}
Lo que parece lógico, ya que el único beneficio de constera evitar jugar con la cadena original (lo que no sucede porque pasé por valor). Pero leí en CPlusPlus.com :
Aunque tenga en cuenta que, en la biblioteca estándar, mover implica que el objeto movido desde se deja en un estado válido pero no especificado. Lo que significa que, después de una operación de este tipo, el valor del objeto desde el que se movió solo debe destruirse o asignarse un nuevo valor; acceder a él de otro modo produce un valor no especificado.
Ahora imagina este código:
std::string nameString("Alex");
Creature c(nameString);
Debido a que nameStringse pasa por valor, std::movesolo se invalidará namedentro del constructor y no tocará la cadena original. Pero, ¿cuáles son las ventajas de esto? Parece que el contenido se copia solo una vez de todos modos: si paso por referencia cuando llamo m_name{name}, si paso por valor cuando lo paso (y luego se mueve). Entiendo que esto es mejor que pasar por valor y no usar std::move(porque se copia dos veces).
Entonces dos preguntas:
- ¿Entendí correctamente lo que está pasando aquí?
- ¿Hay alguna ventaja de usar
std::movesobrepasar por referencia y simplemente llamarm_name{name}?
std::string_viewy el SSO.
clang-tidyes una excelente manera de obsesionarme con microoptimizaciones innecesarias a expensas de la legibilidad. La pregunta que debemos hacer aquí, antes que nada, es cuántas veces llamamos realmente al Creatureconstructor.
Creature c("John");hace una copia adicional