Vektörler, C ++ 'da değere veya başvuruya göre işlevlere geçirilir


98

C ++ ile kodluyorum. Eğer bir fonksiyona sahipsem void foo(vector<int> test)ve onu programımda çağırırsam, vektör değer veya referans ile geçecek mi? Emin değilim çünkü vektörlerin ve dizilerin benzer olduğunu ve gibi bir işlevin void bar(int test[])değeri yerine referansla (işaretçi?) Testi geçeceğini biliyorum . Tahminim, eğer değere göre geçiş yapmaktan kaçınmak istiyorsam, vektörü açıkça işaretçi / referansla geçirmem gerekeceği, ancak emin değilim.


5
C ++ "değere göre geçirme" semantiğine sahiptir, bu nedenle değere göre aktarılır. Yine de referansla geçmeye karar verebilirsiniz. Seçim gerçekten işlevin ne yaptığına bağlıdır.
juanchopanza

2
referans olarak kullanın, fonksiyonun vektör içeriğini değiştirmesini istemiyorsanız sabit yapın, diğer akıllıca bunu referans olarak iletin.
İstenmeyen

3
Ayrıca referans, işaretçi değildir.
The Paramagnetic Kruvasan

2
@AliKazmi Fonksiyonun gövdesinde bir kopyasını istemeniz dışında.
juanchopanza

Neye ulaşmak istediğinize bağlıdır. Standart akıllı işaretçilerden birini kullanmak bazen yararlıdır, örneğin, sahipliği devretmek istiyorsanız, benzersiz_ptr kullanın. Ama genellikle std :: vektörü referans olarak geçiririm.
Erik Alapää

Yanıtlar:


138

Tahmin etmem gerekirse, Java kökenli olduğunuzu söyleyebilirim. Bu C ++ 'dır ve siz &-operatörü kullanarak başka türlü belirtmediğiniz sürece işler değere göre iletilir (bu işlecin aynı zamanda' adresi 'operatörü olarak kullanıldığını, ancak farklı bir bağlamda kullanıldığını unutmayın). Bunların hepsi iyi belgelenmiştir, ancak yine de tekrarlayacağım:

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

Ayrıca bir vektöre ( void foo(vector<int> *bar)) bir işaretçi aktarmayı da seçebilirsiniz , ancak ne yaptığınızı bilmiyorsanız ve bunun gerçekten doğru yol olduğunu hissetmiyorsanız, bunu yapmayın.

Ayrıca vektörler dizilerle aynı değildir ! Vektör, dahili olarak sizin için bellek yönetimini işlediği bir diziyi izler, ancak diğer birçok STL kapsayıcısı da öyle. Bir işaretçi veya dizi bekleyen bir işleve bir vektör iletemezsiniz veya bunun tersi de geçerlidir (temeldeki diziye (işaretçi) erişebilir ve bunu kullanabilirsiniz). Vektörler, üye işlevleri aracılığıyla çok sayıda işlevsellik sunan sınıflardır, işaretçiler ve diziler ise yerleşik türlerdir. Aynı zamanda, vektörler dinamik olarak tahsis edilir (bu, boyutun çalışma zamanında belirlenebileceği ve değiştirilebileceği anlamına gelir), C tarzı diziler statik olarak tahsis edilir (boyutu sabittir ve derleme zamanında bilinmelidir), kullanımlarını sınırlandırır.

Genel olarak C ++ (özellikle dizi bozulması ) hakkında biraz daha okumanızı ve ardından diziler ve işaretçiler arasındaki farkı gösteren aşağıdaki programa bir göz atmanızı öneririm :

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
Son bildirim foo4 işlevini anlamama yardım eden var mı? Neden diğer işlevlerde olduğu gibi gösterici boyutu yerine dizi boyutunu döndürüyor?
abhishek_M

3
@abhishek_M çünkü parametre türü bir referanstır. Bir başvuru yalnızca aynı türden bir ifadeye bağlanabilir. Bu nedenle dizi bozulmaz, çünkü bir diziye yapılan başvuru bir işaretçiye bağlanamaz, yalnızca aynı türden bir diziye bağlanabilir (bu durumda 10 tam sayı dizisi)
bolov

1
c ++ 11'de "taşıma semantiği" vardır ve bunu dikkatli bir şekilde yapabilir ve kopyalama olmadan değere göre (taşıma semantiği ile) geçebilirsiniz. İşte bana çok yardımcı olan bir bağlantı: mbevin.wordpress.com/2012/11/20/move-semantics
fchen

24

A vector, işlevsel olarak bir dizi ile aynıdır. Ama dil vectorbir türdür ve intaynı zamanda bir türdür. Bir işlev bağımsız değişkenine göre, herhangi bir türde (dahil vector[]) bir dizi işaretçi olarak kabul edilir. A vector<int>, int[](derleyiciye) ile aynı değildir . vector<int>dizi olmayan, referans olmayan ve işaretçi olmayan - değere göre iletiliyor ve bu nedenle copy-yapıcıyı çağıracak.

Bu nedenle, referans olarak iletmek için kullanmalısınız vector<int>&(tercihen const, işlev onu değiştirmiyorsa).


Bir işleve referansla bir "vektör dizisi" geçirmenin sözdizimi nedir?
ab123

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

9

void foo(vector<int> test)

vektör, bunda değer tarafından geçirilir.

Bağlama bağlı olarak vektörleri aktarmanın daha fazla yolu var: -

1) Referansla aktar: - Bu, foo fonksiyonunun vektörün içeriğini değiştirmesine izin verir. Vektörün kopyalanması önlendiğinden, değere göre geçirmekten daha etkilidir.

2) Sabit referansa göre aktar: - Bu, işlevin vektörün içeriğini değiştirmesini istemediğinizde verimli ve güvenilirdir.


1

Vektörü argüman olarak bir fonksiyonda değere göre geçirdiğimizde, bu basitçe vektörün kopyasını oluşturur ve bu belirli fonksiyonu çağırdığımızda ana fonksiyonda tanımlanan vektör üzerinde herhangi bir etki olmaz. vektörü, o belirli işlevde yazılanları referans olarak geçirdiğimizde, her eylem, o belirli işlevi çağırdığımızda, ana işlevde veya başka bir işlevde tanımlanan vektör üzerinde gerçekleştirilecektir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.