Os vetores são passados ​​para funções por valor ou por referência em C ++

94

Estou programando em C ++. Se eu tiver alguma função void foo(vector<int> test)e chamá-la no meu programa, o vetor será passado por valor ou referência? Não tenho certeza porque sei que vetores e matrizes são semelhantes e que uma função como void bar(int test[])passaria no teste por referência (ponteiro?) Em vez de por valor. Meu palpite é que eu precisaria passar o vetor por ponteiro / referência explicitamente se quisesse evitar a passagem por valor, mas não tenho certeza.

Adão
fonte
5
C ++ tem semântica de "passagem por valor", portanto, é transmitida por valor. Você pode decidir passar por referência embora. A escolha realmente depende do que a função faz.
juanchopanza
2
use por referência, se você não quiser que a função altere o conteúdo do vetor torne-o constante, caso contrário, apenas passe-o por referência. Isso evitará uma cópia
indesejada
3
Além disso, uma referência não é um ponteiro.
The Paramagnetic Croissant
2
@AliKazmi Exceto se você quiser uma cópia no corpo da função.
juanchopanza
Depende do que você deseja alcançar. Usar um dos ponteiros inteligentes padrão às vezes é útil, por exemplo, se você deseja passar a propriedade, use unique_ptr. Mas normalmente, passo std :: vector por referência.
Erik Alapää

Respostas:

134

Se eu tivesse que adivinhar, diria que você tem experiência em Java. Isso é C ++ e as coisas são passadas por valor, a menos que você especifique de outra forma usando o &operador-(observe que esse operador também é usado como o operador 'endereço de', mas em um contexto diferente). Tudo isso está bem documentado, mas vou reiterar de qualquer maneira:

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

Você também pode escolher passar um ponteiro para um vetor ( void foo(vector<int> *bar)), mas a menos que saiba o que está fazendo e sinta que este é realmente o caminho a percorrer, não faça isso.

Além disso, vetores não são iguais a matrizes! Internamente, o vetor mantém registro de uma matriz da qual ele lida com o gerenciamento de memória para você, mas o mesmo acontece com muitos outros contêineres STL. Você não pode passar um vetor para uma função esperando um ponteiro ou array ou vice-versa (você pode obter acesso (ponteiro para) ao array subjacente e usar isso, entretanto). Vetores são classes que oferecem muitas funcionalidades por meio de suas funções-membro, enquanto ponteiros e arrays são tipos embutidos. Além disso, os vetores são alocados dinamicamente (o que significa que o tamanho pode ser determinado e alterado em tempo de execução), enquanto as matrizes de estilo C são alocadas estaticamente (seu tamanho é constante e deve ser conhecido em tempo de compilação), limitando seu uso.

Eu sugiro que você leia um pouco mais sobre C ++ em geral (especificamente decay de array ) e, em seguida, dê uma olhada no seguinte programa que ilustra a diferença entre arrays e ponteiros:

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
fonte
2
Alguém pode me ajudar a entender a última declaração da função foo4? Por que ele retorna o tamanho da matriz em vez do tamanho do ponteiro, como em outras funções?
abhishek_M
3
@abhishek_M porque o tipo de parâmetro é uma referência. Uma referência pode ser associada apenas a uma expressão exatamente do mesmo tipo. Por esta razão, a matriz não decai, porque uma referência a uma matriz não pode ser associada a um ponteiro, ela só pode ser associada a uma matriz do mesmo tipo (neste caso, matriz de 10 inteiros)
bolov
1
c ++ 11 tem "semântica de movimentação" e você pode fazer isso com cuidado e passar por valor (com semântica de movimentação) sem copiar. Aqui está um link que me ajudou muito: mbevin.wordpress.com/2012/11/20/move-semantics
fchen
23

A vectoré funcionalmente igual a um array. Mas, para a linguagem vectoré um tipo, e inttambém é um tipo. Para um argumento de função, uma matriz de qualquer tipo (incluindo vector[]) é tratada como um ponteiro. A vector<int>não é o mesmo que int[](para o compilador). vector<int>não é array, não é referência e não é ponteiro - está sendo passado por valor e, portanto, chamará o construtor de cópia.

Portanto, você deve usar vector<int>&(de preferência com const, se a função não o estiver modificando) para passá-lo como referência.

Ajay
fonte
Qual é a sintaxe para passar um "array de vetores" por referência a uma função?
ab123
void functionName (std :: vector <int> (& vc) [5]) {}
RIanGillis
9

void foo(vector<int> test)

vetor seria passado por valor neste.

Você tem mais maneiras de passar vetores, dependendo do contexto: -

1) Passagem por referência: - Isso permitirá que a função foo mude o conteúdo do vetor. Mais eficiente do que passar por valor, pois a cópia do vetor é evitada.

2) Passe por referência constante: - Isso é eficiente e confiável quando você não deseja que a função altere o conteúdo do vetor.

Ravi
fonte
1

quando passamos vetor por valor em uma função como um argumento, isso simplesmente cria a cópia do vetor e nenhum efeito acontece no vetor que é definido na função principal quando chamamos essa função particular. ao passo que, quando passamos o vetor por referência tudo o que está escrito naquela função particular, toda ação será executada no vetor que é definido na função principal ou outra função quando chamamos essa função particular.

Nishant Yadav
fonte