He visto una pregunta similar a esta, pero me gustaría una aclaración ...

Suponiendo una clase básica de C ++:

class MyClass
{
public:
    struct SomeData
    {
        std::wstring name;
        std::vector<int> someValues;
    };

    void DoSomething(const SomeData data);
}

Entiendo que data se pasará como const a DoSomething y eso está bien ya que data no será modificado de ninguna manera por la función ... pero estoy acostumbrado para ver & especificado con los parámetros const para garantizar que se pasan por referencia, por ejemplo

void DoSomething(const SomeData& data);

Eso me parece más eficiente. Si omitimos el &, ¿no se pasa data por valor a DoSomething? No estoy seguro de por qué sería preferible pasar un parámetro const por valor cuando puede pasar por referencia y evitar que se produzca la copia.

2
DaveUK 8 sep. 2018 a las 08:07

4 respuestas

La mejor respuesta

Pasar por valor / referencia y corrección constante son dos conceptos diferentes. Pero se usan juntos.

Pase por valor

 void DoSomething (SomeData data);

El paso por valor se utiliza cuando es menos costoso copiar y no desea mantener referencias a objetos extraños. Esta función podría (si está dentro de una clase) mantener un puntero a esto en algún caso y tener su propia copia.

Pasar por referencia

void DoSomething (SomeData& data);

Siempre use pasar por referencia si sabe que esto podría causar una pérdida de rendimiento al copiar la estructura. Esta función podría (si está dentro de una clase) mantener un puntero a esto en algún caso y apuntar a un objeto extraño. Mantener punteros a objetos extraños significa que debe tener en cuenta su tiempo de vida y cuándo este objeto extraño queda fuera del límite. Lo más importante es que los cambios en objetos extraños aparecen en su puntero.

corrección constante

void DoSomething (const SomeData data);  // const for local copy
void DoSomething (const SomeData& data); //  const for callers object

Agregar const para pasar por valor o referencia significa que esta función no lo cambia. Pero no tener o tener & decide qué objeto está intentando agregar seguridad de modificación. const es una herramienta muy útil en C ++ en términos de API de documentación, proporciona seguridad en el tiempo de compilación, permite más optimizaciones del compilador.

Lea este artículo.

4
PraAnj 8 sep. 2018 a las 06:27

El mayor problema con void DoSomething(const SomeData data) es que combina la interfaz y la implementación. Desde el punto de vista de la persona que llama, el const no cambia nada; la función recibe una copia de todos modos y el objeto original no se modifica. Lo que la implementación hace o no con su propia copia interna de funciones no debería molestar a la persona que llama y, por lo tanto, no debe expresarse en la interfaz.

El const hace que la implementación sea más constante si la copia no se modifica, pero filtrar los detalles de la implementación en la interfaz es un alto precio a pagar. Recomiendo no usar void DoSomething(const SomeData data).

Como siempre, las ganancias o pérdidas de rendimiento no deben sobrestimarse aquí. Se trata más de semántica y convenciones.

1
Christian Hackl 8 sep. 2018 a las 09:10

Éste:

void DoSomething(const SomeData data);

Es un poco inusual, porque si bien no cambia nada para la persona que llama (que puede pasar un valor constante o no constante), restringe lo que la función puede hacer internamente. No hay mucho valor en eso, y no se hace comúnmente.

Pasar por referencia (constante o no) es más eficiente si el valor es costoso de copiar, incluso si es mayor que aproximadamente dos punteros en la plataforma de destino. En otras palabras, si SomeData fuera una estructura que contiene dos enteros, probablemente sería más eficiente pasarlo por valor. Pero si contiene un std::map o algunos datos más grandes, mejor páselo por referencia.

Una excepción a esto es que si la función va a copiar el valor de todos modos, entonces es mejor tomarlo por valor, porque el valor podría "moverse" en lugar de copiarse si la persona que lo llama lo permite.

0
John Zwinck 8 sep. 2018 a las 05:24

Pasar un valor const es principalmente informativo para la persona que llama, muestra intención. Esto es importante para que el código sea fácil de leer, comprender y mantener.

También podría ser posible que el compilador agregue algunas optimizaciones adicionales si sabe que la función no modifica su argumento. Por ejemplo, puede hacer que el compilador no realice una copia.

0
Some programmer dude 8 sep. 2018 a las 05:20