Чи передаються вектори функціям за значенням або за посиланням у C ++


94

Я кодую на C ++. Якщо у мене є якась функція, void foo(vector<int> test)і я викликаю її у своїй програмі, чи буде вектор передаватися за значенням чи посиланням? Я не впевнений, бо знаю, що вектори та масиви схожі, і така функція, як void bar(int test[])передаватиме тест за посиланням (покажчиком?), А не за значенням. Я припускаю, що мені потрібно було б передавати вектор за вказівником / посиланням явно, якщо я хотів уникнути передачі за значенням, але я не впевнений.


5
С ++ має семантику "передавати за значенням", тому передається за значенням. Ви можете вирішити передати за посиланням. Вибір насправді залежить від того, що робить функція.
juanchopanza

2
використовуйте за посиланням, якщо функція, яка ви не хочете змінювати векторний вміст, робить її const, в іншому випадку просто передайте її за посиланням. Це дозволить уникнути небажаних та дорогих (іноді) копій
Алі Казмі,

3
Крім того, посилання не є покажчиком.
Парамагнітний круасан

2
@AliKazmi За винятком випадків, коли вам потрібна копія в тілі функції.
juanchopanza

Це залежить від того, чого ви хочете досягти. Використання одного зі стандартних інтелектуальних покажчиків часом корисно, наприклад, якщо ви хочете передати право власності, тоді використовуйте unique_ptr. Але зазвичай я передаю std :: vector за посиланням.
Ерік Алапя

Відповіді:


134

Якби мені довелося здогадуватися, я б сказав, що ви з походження Java. Це C ++, і речі передаються за значенням, якщо ви не вказали інше за допомогою &-operator (зауважте, що цей оператор також використовується як оператор 'address-of', але в іншому контексті). Це все добре задокументовано, але я все одно повторю:

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

Ви також можете передати вказівник на вектор ( void foo(vector<int> *bar)), але якщо ви не знаєте, що робите, і не відчуваєте, що це справді такий шлях, не робіть цього.

Крім того, вектори - це не те саме, що масиви! Внутрішньо вектор відстежує масив, з якого він обробляє управління пам’яттю для вас, але це робить і багато інших контейнерів STL. Ви не можете передати вектор функції, яка очікує вказівника або масиву, або навпаки (ви можете отримати доступ до (вказівника на) базовий масив і використовувати це, хоча). Вектори - це класи, що пропонують багато функціональних можливостей за допомогою своїх функцій-членів, тоді як покажчики та масиви - це вбудовані типи. Крім того, вектори динамічно розподіляються (це означає, що розмір може бути визначений і змінений під час виконання), тоді як масиви у стилі С статично розподіляються (його розмір є постійним і повинен бути відомий під час компіляції), обмежуючи їх використання.

Я пропоную вам прочитати трохи більше про C ++ загалом (зокрема про розпад масивів ), а потім поглянути на наступну програму, яка ілюструє різницю між масивами та покажчиками:

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);
}

2
Хтось може допомогти мені зрозуміти останню декларацію функції foo4? Чому він повертає розмір масиву замість розміру вказівника, як в інших функціях?
abhishek_M

3
@abhishek_M, оскільки тип параметра є посиланням. Посилання може бути прив'язане лише до виразу того самого типу. З цієї причини масив не занепадає, оскільки посилання на масив не може бути прив’язане до вказівника, воно може бути прив’язане лише до масиву того самого типу (в даному випадку масиву з 10 цілих чисел)
bolov

1
c ++ 11 має "семантику переміщення", і ви можете робити це обережно і передавати значення (із семантикою переміщення) без копіювання. Ось посилання, яке мені дуже допомогло: mbevin.wordpress.com/2012/11/20/move-semantics
fchen

23

A vectorфункціонально збігається з масивом. Але мова vector- це тип, і intце теж тип. Для аргументу функції масив будь-якого типу (включаючи vector[]) розглядається як покажчик. A vector<int>- не те саме, що int[](для компілятора). vector<int>не є масивом, не посиланням і не вказівником - він передається за значенням, і, отже, він буде викликати конструктор копіювання.

Отже, ви повинні використовувати vector<int>&(бажано з const, якщо функція не змінює), щоб передати його як посилання.


Який синтаксис для передачі "масиву векторів" за посиланням на функцію?
ab123

void functionName (std :: vector <int> (& vc) [5]) {}
RIanGillis

9

void foo(vector<int> test)

vector буде передано за значенням у цьому.

У вас є більше способів передавати вектори залежно від контексту: -

1) Передайте посилання: - Це дозволить функції foo змінити ваш вміст вектора. Більш ефективно, ніж передавати значення, оскільки уникати копіювання вектора.

2) Передайте const-reference: - Це ефективно, а також надійно, коли ви не хочете, щоб функція змінювала вміст вектора.


1

коли ми передаємо вектор за значенням у функції як аргумент, він просто створює копію вектора, і ніякого впливу на вектор не відбувається, який визначається в основній функції, коли ми викликаємо цю особливу функцію. в той час, коли ми передаємо вектор за посиланням, що б не було записано в цій конкретній функції, кожна дія буде виконуватися над вектором, який визначений в основній або іншій функції, коли ми викликаємо цю особливу функцію.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.