Adalah vektor yang diteruskan ke fungsi berdasarkan nilai atau dengan referensi dalam C ++

97

Saya membuat kode dalam C ++. Jika saya memiliki beberapa fungsi void foo(vector<int> test)dan saya menyebutnya dalam program saya, apakah vektor akan diteruskan oleh nilai atau referensi? Saya tidak yakin karena saya tahu vektor dan array serupa dan fungsi seperti itu void bar(int test[])akan lulus uji dengan referensi (pointer?), Bukan dengan nilai. Dugaan saya adalah bahwa saya harus melewatkan vektor dengan pointer / referensi secara eksplisit jika saya ingin menghindari lewat nilai tetapi saya tidak yakin.

Adam
sumber
5
C ++ memiliki semantik "pass by value", sehingga ia diteruskan oleh nilai. Anda dapat memutuskan untuk melewatkan referensi. Pilihannya sangat tergantung pada apa fungsinya.
juanchopanza
2
Gunakan sebagai referensi, jika Anda tidak ingin fungsi untuk mengubah konten vektor menjadikannya konst, jika tidak, cukup kirimkan dengan referensi. Ini akan menghindari salinan yang tidak diinginkan dan mahal (kadang-kadang)
Ali Kazmi
3
Juga, referensi bukanlah penunjuk.
The Paramagnetic Croissant
2
@AliKazmi Kecuali jika Anda ingin menyalin di badan fungsi.
juanchopanza
Itu tergantung pada apa yang ingin Anda capai. Menggunakan salah satu smart pointer standar terkadang berguna, misalnya jika Anda ingin meneruskan kepemilikan, gunakan unique_ptr. Tapi biasanya, saya meneruskan std :: vector dengan referensi.
Erik Alapää

Jawaban:

136

Jika saya harus menebak, saya akan mengatakan bahwa Anda berasal dari latar belakang Java. Ini adalah C ++, dan hal-hal diteruskan oleh nilai kecuali jika Anda menetapkan sebaliknya menggunakan &-operator (perhatikan bahwa operator ini juga digunakan sebagai operator 'alamat-dari', tetapi dalam konteks yang berbeda). Ini semua terdokumentasi dengan baik, tetapi saya akan mengulangi lagi:

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

Anda juga dapat memilih untuk meneruskan penunjuk ke vektor ( void foo(vector<int> *bar)), tetapi kecuali Anda tahu apa yang Anda lakukan dan Anda merasa bahwa inilah cara yang tepat, jangan lakukan ini.

Juga, vektor tidak sama dengan array! Secara internal, vektor melacak larik yang menangani manajemen memori untuk Anda, tetapi begitu juga banyak container STL lainnya. Anda tidak dapat meneruskan vektor ke fungsi yang mengharapkan pointer atau array atau sebaliknya (Anda bisa mendapatkan akses ke (pointer ke) array yang mendasari dan menggunakannya). Vektor adalah kelas yang menawarkan banyak fungsi melalui fungsi anggotanya, sedangkan pointer dan array adalah tipe bawaan. Juga, vektor dialokasikan secara dinamis (yang berarti bahwa ukurannya dapat ditentukan dan diubah saat runtime) sedangkan array gaya-C dialokasikan secara statis (ukurannya konstan dan harus diketahui pada waktu kompilasi), membatasi penggunaannya.

Saya sarankan Anda membaca lebih lanjut tentang C ++ secara umum (khususnya peluruhan array ), dan kemudian lihat program berikut yang menggambarkan perbedaan antara array dan pointer:

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
sumber
2
Adakah yang bisa membantu saya memahami fungsi deklarasi foo4 terakhir? Mengapa itu mengembalikan ukuran larik daripada ukuran penunjuk seperti di fungsi lain?
abhishek_M
3
@abhishek_M karena tipe parameternya adalah referensi. Referensi hanya dapat diikat ke ekspresi dengan tipe yang sama persis. Untuk alasan ini array tidak membusuk, karena referensi ke array tidak dapat terikat ke pointer, itu hanya dapat diikat ke array dengan tipe yang sama (dalam hal ini array 10 bilangan bulat)
bolov
1
c ++ 11 memiliki "semantik bergerak" dan Anda dapat melakukannya dengan hati-hati dan meneruskan nilai (dengan semantik bergerak) tanpa salinan. Berikut ini tautan yang sangat membantu saya: mbevin.wordpress.com/2012/11/20/move-semantics
fchen
24

A vectorsecara fungsional sama dengan array. Tapi, bahasa vectoradalah tipe, dan intjuga tipe. Untuk argumen fungsi, semua tipe array (termasuk vector[]) diperlakukan sebagai penunjuk. A vector<int>tidak sama dengan int[](ke kompilator). vector<int>adalah non-array, non-reference, dan non-pointer - itu dilewatkan oleh nilai, dan karenanya akan memanggil copy-constructor.

Jadi, Anda harus menggunakan vector<int>&(sebaiknya dengan const, jika fungsi tidak memodifikasinya) untuk meneruskannya sebagai referensi.

Ajay
sumber
Apa sintaks untuk meneruskan "larik vektor" dengan mengacu pada suatu fungsi?
ab123
void functionName (std :: vector <int> (& vc) [5]) {}
RIanGillis
9

void foo(vector<int> test)

vektor akan melewati nilai ini.

Anda memiliki lebih banyak cara untuk meneruskan vektor tergantung pada konteksnya: -

1) Lewati referensi: - Ini akan membiarkan fungsi foo mengubah konten vektor Anda. Lebih efisien daripada nilai lewat karena penyalinan vektor dihindari.

2) Lewati referensi-konst: - Ini efisien dan juga dapat diandalkan ketika Anda tidak ingin berfungsi untuk mengubah konten vektor.

ravi
sumber
1

ketika kita melewatkan vektor dengan nilai dalam suatu fungsi sebagai argumen, itu hanya membuat salinan vektor dan tidak ada efek yang terjadi pada vektor yang didefinisikan dalam fungsi utama ketika kita memanggil fungsi tertentu itu. sedangkan ketika kita melewatkan vektor dengan referensi apa pun yang tertulis dalam fungsi tertentu itu, setiap tindakan akan dilakukan pada vektor yang didefinisikan dalam fungsi utama atau lainnya ketika kita memanggil fungsi tertentu itu.

Nishant Yadav
sumber