¿Se pasan vectores a funciones por valor o por referencia en C ++?

94

Estoy codificando en C ++. Si tengo alguna función void foo(vector<int> test)y la llamo en mi programa, ¿se pasará el vector por valor o referencia? No estoy seguro porque sé que los vectores y las matrices son similares y que una función como void bar(int test[])pasaría la prueba por referencia (¿puntero?) En lugar de por valor. Supongo que necesitaría pasar el vector por puntero / referencia explícitamente si quisiera evitar pasar por valor, pero no estoy seguro.

Adán
fuente
5
C ++ tiene semántica de "pasar por valor", por lo que se pasa por valor. Sin embargo, puede decidir pasar por referencia. La elección realmente depende de lo que haga la función.
juanchopanza
2
use por referencia, si la función que no desea cambiar el contenido del vector, hágalo constante, de lo contrario, simplemente páselo por referencia.
Evitará
3
Además, una referencia no es un puntero.
El croissant paramagnético
2
@AliKazmi Excepto si desea una copia en el cuerpo de la función.
juanchopanza
Depende de lo que quieras lograr. El uso de uno de los punteros inteligentes estándar a veces es útil, por ejemplo, si desea transferir la propiedad, use unique_ptr. Pero generalmente, paso std :: vector por referencia.
Erik Alapää

Respuestas:

134

Si tuviera que adivinar, diría que tiene experiencia en Java. Esto es C ++, y las cosas se pasan por valor a menos que especifique lo contrario usando el &-operador (tenga en cuenta que este operador también se usa como el operador 'dirección de', pero en un contexto diferente). Todo esto está bien documentado, pero repetiré de todos modos:

void foo(vector<int> bar); // by value
void foo(vector<int> &bar); // by reference (non-const, so modifiable inside foo)
void foo(vector<int> const &bar); // by const-reference

También puede optar por pasar un puntero a un vector ( void foo(vector<int> *bar)), pero a menos que sepa lo que está haciendo y sienta que este es realmente el camino a seguir, no lo haga.

Además, los vectores no son lo mismo que las matrices. Internamente, el vector realiza un seguimiento de una matriz de la que gestiona la memoria por usted, pero también lo hacen muchos otros contenedores STL. No puede pasar un vector a una función que espera un puntero o matriz o viceversa (puede obtener acceso (puntero a) la matriz subyacente y usar esto). Los vectores son clases que ofrecen mucha funcionalidad a través de sus funciones miembro, mientras que los punteros y las matrices son tipos integrados. Además, los vectores se asignan dinámicamente (lo que significa que el tamaño se puede determinar y cambiar en tiempo de ejecución) mientras que los arreglos de estilo C se asignan estáticamente (su tamaño es constante y debe conocerse en tiempo de compilación), lo que limita su uso.

Le sugiero que lea un poco más sobre C ++ en general (específicamente la desintegración de matrices ) y luego eche un vistazo al siguiente programa que ilustra la diferencia entre matrices y punteros:

void foo1(int *arr) { cout << sizeof(arr) << '\n'; }
void foo2(int arr[]) { cout << sizeof(arr) << '\n'; }
void foo3(int arr[10]) { cout << sizeof(arr) << '\n'; }
void foo4(int (&arr)[10]) { cout << sizeof(arr) << '\n'; }

int main()
{
    int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    foo1(arr);
    foo2(arr);
    foo3(arr);
    foo4(arr);
}
JorenHeit
fuente
2
¿Alguien puede ayudarme a entender la última función de declaración foo4? ¿Por qué devuelve el tamaño de la matriz en lugar del tamaño del puntero como en otras funciones?
abhishek_M
3
@abhishek_M porque el tipo de parámetro es una referencia. Una referencia solo puede estar vinculada a una expresión del mismo tipo exacto. Por esta razón, la matriz no decae, porque una referencia a una matriz no se puede vincular a un puntero, solo se puede vincular a una matriz del mismo tipo (en este caso, matriz de 10 enteros)
bolov
1
c ++ 11 tiene "semántica de movimiento" y puede hacerlo con cuidado y pasar por valor (con semántica de movimiento) sin copiar. Aquí hay un enlace que me ayudó mucho: mbevin.wordpress.com/2012/11/20/move-semantics
fchen
23

A vectores funcionalmente igual que una matriz. Pero para el lenguaje vectores un tipo, y inttambién es un tipo. Para un argumento de función, una matriz de cualquier tipo (incluido vector[]) se trata como puntero. A vector<int>no es lo mismo que int[](para el compilador). vector<int>es sin matriz, sin referencia y sin puntero: se pasa por valor y, por lo tanto, llamará al constructor de copia.

Por lo tanto, debe usar vector<int>&(preferiblemente con const, si la función no lo está modificando) para pasarlo como referencia.

Ajay
fuente
¿Cuál es la sintaxis para pasar una "matriz de vectores" por referencia a una función?
ab123
void functionName (std :: vector <int> (& vc) [5]) {}
RIanGillis
9

void foo(vector<int> test)

vector se pasaría por valor en este.

Tiene más formas de pasar vectores según el contexto: -

1) Pasar por referencia: - Esto permitirá que la función foo cambie el contenido del vector. Más eficiente que pasar por valor, ya que se evita la copia de vectores.

2) Pasar por referencia constante: - Esto es eficiente y confiable cuando no desea que la función cambie el contenido del vector.

ravi
fuente
1

cuando pasamos vector por valor en una función como argumento, simplemente crea la copia del vector y no ocurre ningún efecto en el vector que se define en la función principal cuando llamamos a esa función en particular. mientras que cuando pasamos vector por referencia lo que esté escrito en esa función en particular, cada acción se realizará en el vector que está definido en la función principal u otra cuando llamamos a esa función en particular.

Nishant Yadav
fuente