He visto numerosos argumentos de que usar un valor de retorno es preferible a los parámetros de salida. Estoy convencido de las razones por las cuales evitarlos, pero no estoy seguro de si me estoy encontrando con casos en los que es inevitable.Cómo evitar los parámetros?
Parte 1 de mi pregunta es: ¿Cuáles son algunas de sus formas favoritas/comunes de moverse utilizando un parámetro out? Cosas como las siguientes: Hombre, en las revisiones por pares siempre veo a otros programadores hacer esto cuando podrían haberlo hecho de esta manera.
Parte Dos Parte de mi pregunta se refiere a algunos casos específicos que he encontrado donde me gustaría evitar un parámetro de salida pero no puedo pensar en una manera limpia de hacerlo.
Ejemplo 1: Tengo una clase con una copia costosa que me gustaría evitar. Se puede trabajar en el objeto y esto crea el objeto que será costoso de copiar. El trabajo para construir los datos tampoco es trivial. Actualmente, pasaré este objeto a una función que modificará el estado del objeto. Para mí, esto es preferible a actualizar el objeto interno a la función de trabajador y devolverlo, ya que me permite mantener las cosas en la pila. código
class ExpensiveCopy //Defines some interface I can't change.
{
public:
ExpensiveCopy(const ExpensiveCopy toCopy){ /*Ouch! This hurts.*/ };
ExpensiveCopy& operator=(const ExpensiveCopy& toCopy){/*Ouch! This hurts.*/};
void addToData(SomeData);
SomeData getData();
}
class B
{
public:
static void doWork(ExpensiveCopy& ec_out, int someParam);
//or
// Your Function Here.
}
Usando mi función, consigo llamar así:
const int SOME_PARAM = 5;
ExpensiveCopy toModify;
B::doWork(toModify, SOME_PARAM);
me gustaría tener algo como esto:
ExpensiveCopy theResult = B::doWork(SOME_PARAM);
Pero no sé si esto es posible.
Segundo ejemplo: Tengo una matriz de objetos. Los objetos en la matriz son de un tipo complejo, y necesito trabajar en cada elemento, trabajo que me gustaría mantener separado del bucle principal que accede a cada elemento. El código actualmente se ve así:
std::vector<ComplexType> theCollection;
for(int index = 0; index < theCollection.size(); ++index)
{
doWork(theCollection[index]);
}
void doWork(ComplexType& ct_out)
{
//Do work on the individual element.
}
¿Alguna sugerencia sobre cómo lidiar con algunas de estas situaciones? Trabajo principalmente en C++, pero estoy interesado en ver si otros idiomas facilitan una configuración más sencilla. Me he encontrado con RVO como una posible solución, pero necesito leer más sobre él y me parece una característica específica del compilador.
La semántica de un parámetro de referencia no constante es que se (puede) modificarse en la función. Si no fuera a cambiarlo, lo pasaría como una referencia constante, después de todo. – Bill
* "pero estoy interesado en ver si otros idiomas facilitan una configuración más sencilla" *: los lenguajes como Java y C# simplemente no tienen ese problema, ya que siempre hacen referencias a objetos a su alrededor. –
Maravillosas respuestas de todos. Tenía la sensación de que en mis ejemplos específicos no habría muchas otras opciones.He visto publicaciones en SO de personas que son tan inflexibles sobre cómo evitan los parámetros a toda costa. Esperaba que tal vez uno de ellos pudiera explicar cómo lograron tal hazaña. En cuanto a RVO, tengo cierto reparo en usar funciones específicas del compilador, ya que sería difícil explicar a mis jefes por qué tengo que rediseñar la mitad de mi código porque ya no funciona debido a una característica que falta como resultado de una cambio/actualización del compilador –