Bir diziyi başvuru ile iletme


184

Statik olarak tahsis edilmiş bir diziyi başvuru ile geçmek nasıl çalışır?

void foo(int (&myArray)[100])
{
}

int main()
{
    int a[100];
    foo(a);
}

Does (&myArray)[100]referans ile herhangi dizi geçmesine herhangi bir anlam veya onun sadece bir sözdizimi var? Burada ayrı parantez ve ardından büyük parantez anlamıyorum. Teşekkürler.


Fonksiyon parametreleri ile Rvalue to Lvalue ilişkisi var mı?
John DB


Yanıtlar:


228

Dizi referansları için bir sözdizimi - (&array)derleyiciye (geçersiz) referans dizisi yerine bir diziye başvuru yapmak istediğinizi açıklığa kavuşturmak için kullanmanız gerekir int & array[100];.

EDIT: Bazı açıklamalar.

void foo(int * x);
void foo(int x[100]);
void foo(int x[]);

Bu üçü aynı işlevi bildirmenin farklı yollarıdır. Hepsi bir int *parametre almak olarak kabul edilir , onlara herhangi bir boyut dizisi iletebilirsiniz.

void foo(int (&x)[100]);

Bu yalnızca 100 tamsayı dizisini kabul eder. Güvenle kullanabilirsiniz sizeofüzerindex

void foo(int & x[100]); // error

Bu, yasal olmayan bir "referans dizisi" olarak ayrıştırılır.


Neden bir referans dizimiz olamaz int a, b, c; int arr[3] = {a, b, c};?
Vorac

4
Aha, nedenini buldu .
Vorac

2
Birisi neden void foo(int & x[100]);"referans dizisi" olarak ayrıştırıldığını açıklayabilir mi? Bunun nedeni "sağdan sola" kuralı mı? Evetse, void foo(int (&x)[100]);"bir diziye başvuru" olarak ayrıştırılma biçimiyle tutarlı görünmüyor . Şimdiden teşekkürler.
zl9394

3
Sola doğru değil, içeriden dışarıya doğru ve [] & 'dan daha sıkı bağlanır.
philipxy

48

Sadece gerekli sözdizimi:

void Func(int (&myArray)[100])

^ intParametrelerin ismini referans alarak 100'lük bir dizi dizisi myArray;

void Func(int* myArray)

^ Bir dizi geçirin. Dizi bir işaretçiye bozulur. Böylece boyut bilgilerini kaybedersiniz.

void Func(int (*myFunc)(double))

^ Bir fonksiyon işaretçisini iletiniz. Fonksiyon a döndürür intve a alır double. Parametre adı myFunc.


Değişken boyutlu bir diziyi referans olarak nasıl iletiriz?
Shivam Arora

@ShivamArora İşlevi şablonlaştırır ve boyutu bir şablon parametresi yaparsınız.
Martin York

24

Bir sözdizimidir. Fonksiyon argümanlarında int (&myArray)[100]parantez içine &myArrayalınması gereklidir. Eğer onları kullanmazsanız, bir geçiyor olacaksınız array of referencesve çünkü subscript operator []daha yüksek önceliğe sahiptir & operator.

Örneğin int &myArray[100] // array of references

Yani, kullanarak type construction ()derleyiciye 100 tamsayı bir dizi başvurusu istediğinizi söyleyin.

Örneğin int (&myArray)[100] // reference of an array of 100 ints


"Eğer onları kullanmazsanız, bir array of references" geçeceksiniz "- ki elbette var olamaz, bu yüzden derleme hatası alırsınız. Operatör öncelik kurallarının bunun zaten varsayılan olarak olması gerektiği konusunda ısrar etmeleri beni eğlendiriyor.
underscore_d

Type construction () hakkında daha fazla öğretici var mı?
Şef Vardiya

Teşekkürler, neden bu şekilde yapılması gerektiğine dair bir fikir veren, operatör önceliği ile ilgili nedeni içeren bir açıklamaya ihtiyacım vardı.
cram2208

4

Diziler varsayılan olarak işaretçilerden geçirilir. Daha iyi anlamak için bir işlev çağrısının içindeki bir diziyi değiştirmeyi deneyebilirsiniz.


2
Diziler değere göre iletilemez. İşlev bir işaretçi alırsa, bir dizi bir işaretçiye ilk öğesinin bozulmasına neden olur. Burada ne söylemeye çalıştığından emin değilim.
Ulrich Eckhardt

@UlrichEckhardt Daha önce de söylediğin gibi "Diziler değere göre geçirilemez" demeye çalışıyorum, varsayılan olarak referans ile geçildi
Eduardo A. Fernández Díaz

8
Dizi ne değer ne de referans tarafından iletilir. Bunlar işaretçilerden geçer. Diziler varsayılan olarak başvuru ile iletilirse, üzerlerinde sizeof komutunu kullanırken sorun yaşamayacaksınız. Ancak durum böyle değil. Diziler, bir işleve iletildiğinde işaretçilere bozulur.
user3437460

2
Diziler, referans VEYA bir işaretçiye indirgenerek iletilebilir. Örneğin char arr[1]; foo(char arr[])., arr öğesi bir işaretçiye dönüşür; kullanırken char arr[1]; foo(char (&arr)[1]), arr referans olarak geçirilir. Boyut kaybolduğundan, eski formun genellikle kötü biçimlenmiş olarak kabul edilmesi dikkat çekicidir.
zl9394

Re, "Diziler ... işaretçilerden geçti." Bu açıklama en iyi ihtimalle sıra dışı geliyor ve yeni başlayanlar için kafa karıştırıcı olabilir. Adı , bir dizi değişkenin, değeri bir işaretçi dizisi ilk üyesi olan geçerli bir ifadesidir. Eğer bazı fonksiyonlarınız varsa foo(T* t)ve bir diziniz varsa, T a[N];o zaman yazdığınızda foo(a);, bir dizi geçirmediğinizi, bir diziyi geçmediğinizi ve işaretçiyi değere geçirdiğinizi söylemek daha doğru olacağını düşünüyorum.
Solomon Yavaş

1

Aşağıdakiler, referans olarak herhangi bir boyutta ve herhangi bir türde bir dizi alarak genel bir işlev oluşturur:

template<typename T, std::size_t S>
void my_func(T (&arr)[S]) {
   // do stuff
}

kod ile oynamak.

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.