Arasındaki fark nedir
- referansla iletilen bir parametre
- bir parametre değerden mi geçti?
Bana birkaç örnek verebilir misiniz?
Arasındaki fark nedir
Bana birkaç örnek verebilir misiniz?
Yanıtlar:
İlk ve en önemlisi, CS teorisinde tanımlanan "değere göre geçişle referans ile geçiş" ayrımı artık geçersizdir çünkü başlangıçta "referansla geçiş" olarak tanımlanan teknik o zamandan beri lehte düşmüştür ve nadiren kullanılmaktadır. 1
Daha yeni diller 2 , birincil karışıklık kaynağı olan aynı etkileri (aşağıya bakınız) elde etmek için farklı (ama benzer) bir çift teknik kullanma eğilimindedir .
İkincil bir karışıklık kaynağı , "referans ile geç" te, "referans" ın, "referans" genel teriminden daha dar bir anlama sahip olmasıdır (cümle daha önce gelir).
Şimdi, otantik tanım:
Bir parametre referans olarak iletildiğinde , arayan ve arayan parametre için aynı değişkeni kullanır . Callee parametre değişkenini değiştirirse, efekt arayanın değişkeni tarafından görülebilir.
Bir parametre değere göre iletildiğinde , arayan ve arayan aynı değerde iki bağımsız değişkene sahiptir. Callee parametre değişkenini değiştirirse, efekt arayan tarafından görülemez.
Bu tanımda dikkat edilmesi gerekenler:
"Değişken" burada arayanın (yerel veya global) değişkeninin kendisi anlamına gelir - yani yerel bir değişkeni referans olarak iletir ve ona atarsam, arayanın değişkenini değiştiririm, örneğin bir işaretçi ise işaret ettiği her şeyi değil .
"Referansla geç" içindeki "referans" ın anlamı . Genel "referans" terimi ile fark, bu "referans" ın geçici ve örtük olmasıdır. Callee'nin temelde aldığı şey, bir şekilde orijinal olanla aynı olan bir "değişken" tir . Bu etkinin spesifik olarak nasıl elde edildiği önemsizdir (örneğin, dil bazı uygulama ayrıntılarını da gösterebilir - adresler, işaretçiler, kayıttan çıkarılma - bunların hepsi önemsizdir; eğer net etki bu ise, referans yoluyla).
Şimdi, modern dillerde, değişkenler "referans türleri" olma eğilimindedir ("referans ile geç" den sonra icat edilmiş ve esinlenerek oluşturulmuş başka bir kavram), yani gerçek nesne verileri ayrı bir yerde (genellikle yığın üzerinde) saklanır ve sadece "referanslar" değişkenlerde tutulur ve parametre olarak iletilir. 3
Böyle bir referansı geçmek, değerin altına düşer, çünkü bir değişkenin değeri teknik olarak referans nesnedir, referanslanan nesne değildir. Bununla birlikte, program üzerindeki net etki, değere göre ya da başvuruya göre aynı olabilir:
Gördüğünüz gibi, bu teknik çifti tanımdaki tekniklerle hemen hemen aynıdır, sadece dolaylı bir düzeydedir: sadece "değişken" i "başvurulan nesne" ile değiştirin.
Onlar için üzerinde anlaşmaya varılmış bir isim yoktur, bu da "değerin referans olduğu değere göre çağrı" gibi çarpık açıklamalara yol açar. 1975 yılında Barbara Liskov, "tamamen nesne paylaşma çağrısı" (ya da bazen sadece "paylaşma çağrısı") terimini önermedi . Dahası, bu cümlelerin hiçbiri orijinal çiftle paralellik göstermez. Eski terimlerin daha iyi bir şeyin yokluğunda yeniden kullanılmasına ve şaşkınlığa yol açmasına şaşmamalı. 4
NOT : Uzun zamandır bu cevap şöyle derdi:
Diyelim ki bir web sayfasını sizinle paylaşmak istiyorum. Size URL'yi söylersem, referansla geçiyorum. Gördüğüm aynı web sayfasını görmek için bu URL'yi kullanabilirsiniz. Bu sayfa değiştirilirse, ikimiz de değişiklikleri görürüz. URL'yi silerseniz, yaptığınız tek şey o sayfaya olan başvurunuzu yok etmektir; gerçek sayfanın kendisini silmiyorsunuzdur.
Sayfayı yazdırıp çıktısını verirsem, değere göre geçiyorum. Sayfanız orijinalin bağlantısı kesilmiş bir kopyası. Sonraki değişiklikleri görmezsiniz ve yaptığınız değişiklikler (örneğin, çıktıda karalama) orijinal sayfada görünmez. Çıktıyı imha ederseniz, aslında nesnenin kopyanızı imha ettiniz - ancak orijinal web sayfası olduğu gibi kalır.
Bu "referans" ın daha dar anlamı dışında çoğunlukla doğrudur - hem geçici hem de örtük (zorunlu değildir, ancak açık ve / veya kalıcı olması, referans by-pass semantiğinin bir parçası değildir, ek özelliklerdir , yukarıda açıklandığı gibi). Daha yakın bir benzetme, bir belgenin bir kopyasını size orijinal üzerinde çalışmaya davet etmekle karşılaştırır.
1 Fortran veya Visual Basic'te programlama yapmadığınız sürece, bu varsayılan davranış değildir ve modern kullanımdaki çoğu dilde, gerçek referans çağrı bile mümkün değildir.
2 Oldukça fazla yaşlı olanlar da bunu destekliyor
3 Birkaç modern dilde, tüm türler referans türleridir. Bu yaklaşıma 1975 yılında CLU dili öncülük etmiştir ve o zamandan beri Python ve Ruby dahil olmak üzere birçok dil tarafından benimsenmiştir. Ve daha birçok dilde, bazı türlerin "değer türleri" ve diğerlerinin "referans türleri" olduğu karma aralıklar kullanılır; bunlar arasında C #, Java ve JavaScript bulunur.
4 Eski bir terimin uygun bir şekilde geri dönüştürülmesinde kötü bir şey yoktur , ancak her seferinde hangi anlamın kullanıldığını bir şekilde açıklığa kavuşturmak gerekir. Bunu yapmamak, tam olarak karışıklığa neden olan şeydir.
Bu, işlevlere argüman aktarmanın bir yoludur. Referans yoluyla geçme, çağrılan fonksiyonların parametresi, arayanların geçirilen argümanı ile aynı olacaktır (değer değil, kimlik - değişkenin kendisi). Değere göre geçirme, çağrılan işlevlerin parametresi, arayanların geçirilen bağımsız değişkeninin bir kopyası olacağı anlamına gelir. Değer aynı olacaktır, ancak kimlik - değişken - farklıdır. Bu nedenle, çağrılan işlev tarafından yapılan bir parametrede yapılan değişiklikler bir durumda geçirilen argümanı değiştirir ve diğer durumda sadece çağrılan işlevdeki (yalnızca bir kopya olan) parametrenin değerini değiştirir. Acele edin:
ref
kullanılan ve işlev olarak adlandırılan anahtar kelime ). Jon Skeet'in de burada güzel bir açıklaması var .Kodlar
Dilim C ++ olduğundan, burada kullanacağım
// passes a pointer (called reference in java) to an integer
void call_by_value(int *p) { // :1
p = NULL;
}
// passes an integer
void call_by_value(int p) { // :2
p = 42;
}
// passes an integer by reference
void call_by_reference(int & p) { // :3
p = 42;
}
// this is the java style of passing references. NULL is called "null" there.
void call_by_value_special(int *p) { // :4
*p = 10; // changes what p points to ("what p references" in java)
// only changes the value of the parameter, but *not* of
// the argument passed by the caller. thus it's pass-by-value:
p = NULL;
}
int main() {
int value = 10;
int * pointer = &value;
call_by_value(pointer); // :1
assert(pointer == &value); // pointer was copied
call_by_value(value); // :2
assert(value == 10); // value was copied
call_by_reference(value); // :3
assert(value == 42); // value was passed by reference
call_by_value_special(pointer); // :4
// pointer was copied but what pointer references was changed.
assert(value == 10 && pointer == &value);
}
Java'daki bir örnek zarar vermez:
class Example {
int value = 0;
// similar to :4 case in the c++ example
static void accept_reference(Example e) { // :1
e.value++; // will change the referenced object
e = null; // will only change the parameter
}
// similar to the :2 case in the c++ example
static void accept_primitive(int v) { // :2
v++; // will only change the parameter
}
public static void main(String... args) {
int value = 0;
Example ref = new Example(); // reference
// note what we pass is the reference, not the object. we can't
// pass objects. The reference is copied (pass-by-value).
accept_reference(ref); // :1
assert ref != null && ref.value == 1;
// the primitive int variable is copied
accept_primitive(value); // :2
assert value == 0;
}
}
Vikipedi
http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_value
http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_reference
Bu adam hemen hemen çiviler:
Buradaki birçok cevap (ve özellikle en çok onaylanan cevap) aslında yanlıştır, çünkü "referans ile çağırma" nın gerçekten ne anlama geldiğini yanlış anlarlar. İşte sorunları düzeltmeye çalışıyorum.
En basit ifadeyle:
Mecazi anlamda:
Bu kavramların her ikisinin de referans türleri kavramından tamamen bağımsız ve dikey olduğuna dikkat edin (Java'da alt türlerde Object
ve C # tüm class
türlerinde tüm türlerdir) veya C'de (semantik olarak eşdeğer olan) işaretçi türleri kavramında Java'nın "referans türleri" ne, yalnızca farklı sözdizimiyle).
Referans türü kavramı bir URL'ye karşılık gelir: her ikisi de kendisi bir bilgi parçasıdır ve diğer bilgilere bir referanstır ( eğer isterseniz bir işaretçi ). Bir URL'nin farklı yerlerde çok sayıda kopyasına sahip olabilirsiniz ve hepsinin bağlantı verdikleri web sitesini değiştirmezler; web sitesi güncellenirse, her URL kopyası yine de güncellenmiş bilgilere yol açar. Tersine, URL'yi herhangi bir yerde değiştirmek, URL'nin yazılı başka bir kopyasını etkilemez.
Not C ++ "referanslar" (örneğin bir nosyonu vardır int&
olduğunu) değil Java ve C # gibi 'ın 'referans türleri', ama bir 'referans ile çağrı' gibi. Java ve C # 'ın "referans türleri" ve Python'daki tüm türler, C ve C ++' nın "işaretçi türleri" (ör. int*
) Olarak adlandırdığı gibidir.
Tamam, işte daha uzun ve daha resmi bir açıklama.
Öncelikle, bazı önemli terminoloji parçalarını vurgulamak, cevabımı açıklığa kavuşturmak ve kelimeleri kullanırken hepimizin aynı fikirlere atıfta bulunmasını sağlamak istiyorum. (Uygulamada, bu tür konularla ilgili kafa karışıklığının büyük çoğunluğunun, amaçlanan anlamı tam olarak iletmeyecek şekilde kelimeler kullanmaktan kaynaklandığına inanıyorum.)
Başlamak için, bir işlev bildiriminin bazı C benzeri dillerinde bir örnek:
void foo(int param) { // line 1
param += 1;
}
İşte bu işlevi çağırmanın bir örneği:
void bar() {
int arg = 1; // line 2
foo(arg); // line 3
}
Bu örneği kullanarak, bazı önemli terminoloji parçalarını tanımlamak istiyorum:
foo
satır 1'de bildirilen bir işlevdir (Java, tüm işlev yöntemlerini yapmakta ısrar eder, ancak genelleme kaybı olmadan kavram aynıdır; C ve C ++, buraya girmeyeceğim bildirim ve tanım arasında bir ayrım yapar)param
Bir edilmektedir biçimsel parametre için foo
, ayrıca 1. satırda beyanarg
2. satırda bildirilen ve başlatılan bir değişken , özellikle işlevin yerel bir değişkenibar
arg
bir de bağımsız değişken belirli için çağırma ve foo
hat 3Burada ayırt edilecek iki önemli kavram kümesi vardır. Birincisi, değişkene karşı değerdir :
bar
yukarıda belirtilen fonksiyon, satır sonra int arg = 1;
, ekspresyon arg
vardır değeri 1
.final
veya C # 'ları kullanılarak bildirilir readonly
) veya derinden değişmez (örn. C ++' lar kullanılarak const
) olabilir.Diğer önemli kavram çifti, parametreye karşı argümandır :
Değere göre çağrıda , işlevin resmi parametreleri, işlev çağırma için yeni oluşturulan ve bağımsız değişkenlerinin değerleri ile başlatılan değişkenlerdir.
Bu, diğer değişkenlerin değerlerle başlatıldığı gibi çalışır. Örneğin:
int arg = 1;
int another_variable = arg;
Burada arg
ve another_variable
tamamen bağımsız değişkenlerdir - değerleri birbirinden bağımsız olarak değişebilir. Bununla birlikte, another_variable
beyan edildiği noktada , aynı değeri tutmaya başlar arg
- ki bu1
.
Bağımsız değişkenler olduklarından, yapılacak değişiklikler şunları another_variable
etkilemez arg
:
int arg = 1;
int another_variable = arg;
another_variable = 2;
assert arg == 1; // true
assert another_variable == 2; // true
Bu tam arasındaki ilişki ile aynıdır arg
ve param
ben simetri için buraya tekrarlayacağız Yukarıdaki örneğimizde,:
void foo(int param) {
param += 1;
}
void bar() {
int arg = 1;
foo(arg);
}
Tam olarak kodu bu şekilde yazmıştık:
// entering function "bar" here
int arg = 1;
// entering function "foo" here
int param = arg;
param += 1;
// exiting function "foo" here
// exiting function "bar" here
Yani, değere göre çağrının ne anlama geldiğinin tanımlayıcı özelliği , callee'nin ( foo
bu durumda) değerleri bağımsız değişken olarak alması , ancak arayanın değişkenlerinden bu değerler için kendi ayrı değişkenlerine sahip olmasıdır (bar
bu durumda) .
Yukarıdaki metaforuma geri dönersem, eğer ben bar
ve sen foo
, seni aradığımda, üzerinde yazılı bir değere sahip bir kağıt parçası veririm . Sen buna kağıt parçası diyorsun param
. Bu değer, defterimde (yerel değişkenlerim), aradığım bir değişkende yazdığım değerin bir kopyasıarg
.
(Bir yana: donanım ve işletim sistemine bağlı olarak, bir işlevi diğerinden nasıl çağırdığınızla ilgili çeşitli çağrı kuralları vardır . Çağrı kuralı, değeri kağıdımın bir parçasına yazıp yazmayacağımı kararlaştırmak gibidir. ya da üzerine yazdığım bir kağıdınız varsa ya da ikimizin önündeki duvara yazarsam. Bu da ilginç bir konudur, ancak bu uzun cevabın kapsamı dışındadır.)
Gelen referans olarak çağrı , işlevin biçimsel parametreler sade yeni isimler aynı değişkenlerin argümanları olarak o arayan malzemeleri için.
Yukarıdaki örneğimize geri dönersek, şuna eşittir:
// entering function "bar" here
int arg = 1;
// entering function "foo" here
// aha! I note that "param" is just another name for "arg"
arg /* param */ += 1;
// exiting function "foo" here
// exiting function "bar" here
Çünkü param
sadece başka bir isim arg
- yani aynı değişkendir , değişiklikler param
yansıtılır arg
. Bu, referansla yapılan çağrının, değere göre çağrıdan farklı olmasının temel yoludur.
Çok az sayıda dil referans ile çağrıyı destekler, ancak C ++ bunu şu şekilde yapabilir:
void foo(int& param) {
param += 1;
}
void bar() {
int arg = 1;
foo(arg);
}
Bu durumda, gerçekte olduğu gibi param
aynı değere sahip değildir , (sadece farklı bir adla) ve artmış olduğunu gözlemleyebilir .arg
arg
bar
arg
Not Bu olduğunu değil nasıl Java, JavaScript, C, Objective-C, Python ya da neredeyse herhangi bir başka popüler dil bugün eserlerin herhangi. Bu diller olan bu araçlar değil referans olarak diyoruz, onlar değere göre çağrı vardır.
Sahip olduğunuz değer değere göre çağrı ise , ancak gerçek değer bir başvuru türü veya işaretçi türüyse , "değer" in kendisi çok ilginç değildir (örneğin, C'de yalnızca platforma özgü bir boyutun tamsayısıdır) - ne ilginç olan bu değerin ne olduğudur .
Bu referans türünün (yani, işaretçinin) işaret ettiği şey değiştirilebilirse , ilginç bir etki mümkündür: sivri uç değerini değiştirebilir ve arayan, çağıramazsa da sivri uç değerinde değişiklikler gözlemleyebilir işaretçinin kendisine değişir.
URL'nin benzetmesini tekrar ödünç almak için, URL'nin bir kopyasını size bir web sitesine verdim , ikimizin de önem verdiği şey URL değil, web sitesi ise özellikle ilginç değildir. URL kopyanızı karalamak sizin URL kopyamı etkilememesi sizin için önemli bir şey değildir (ve aslında Java ve Python gibi dillerde "URL" veya referans türü değeri, hiç değiştirilemez, sadece işaret ettiği şey olabilir).
Barbara Liskov, (bu semantiğe sahip olan) CLU programlama dilini icat ettiğinde, mevcut "değere göre çağrı" ve "referans olarak çağrı" terimlerinin bu yeni dilin anlambilimini tanımlamak için özellikle yararlı olmadığını fark etti. Böylece yeni bir terim icat etti: nesne paylaşımıyla çağrı .
Teknik olarak değere göre çağrılan, ancak kullanımda yaygın olan türlerin referans veya işaretçi türleri olduğu (yani: hemen hemen her modern zorunluluk, nesne yönelimli veya çok paradigma programlama dili) olduğu dilleri tartışırken, bunun daha az kafa karıştırıcı olduğunu düşünüyorum sadece değere göre arama veya referans olarak arama hakkında konuşmaktan kaçının . Nesne paylaşımıyla çağrı yapmak için sopa (veya sadece nesne ile çağrı ) ve kimse karışmaz. :-)
The first is value versus variable.
The other important pair of concepts to distinguish is parameter versus argument:
2 terimi anlamadan önce aşağıdakileri anlamanız GEREKİR . Her nesnenin ayırt edilebilecek 2 şeyi vardır.
Yani diyorsan employee.name = "John"
hakkında 2 şey olduğunu biliyorum name
. Değeridir, bu değer "John"
ve ayrıca belki bu gibi bazı onaltılık sayıdır bellekte konumu: 0x7fd5d258dd00
.
Dilin mimarisine veya nesnenizin türüne (sınıf, yapı vb.) Bağlı olarak, aktarma "John"
veya0x7fd5d258dd00
Geçme "John"
, değere göre geçme olarak bilinir. Geçme 0x7fd5d258dd00
, referans olarak geçme olarak bilinir. Bu bellek konumuna işaret eden herkes, değerine erişebilir "John"
.
Bu konuda daha fazla bilgi için, bir işaretçinin kaydının silinmesi ve neden sınıf (yapı türü) üzerinde yapı (değer türü) seçildiğini okumanızı öneririz.
İşte bir örnek:
#include <iostream>
void by_val(int arg) { arg += 2; }
void by_ref(int&arg) { arg += 2; }
int main()
{
int x = 0;
by_val(x); std::cout << x << std::endl; // prints 0
by_ref(x); std::cout << x << std::endl; // prints 2
int y = 0;
by_ref(y); std::cout << y << std::endl; // prints 2
by_val(y); std::cout << y << std::endl; // prints 2
}
y
önceki satır tarafından 2'ye ayarlanmış. Neden 0'a geri dönecek?
Bunu almanın en basit yolu bir Excel dosyasındadır. Diyelim ki A1 ve B1 hücrelerinde 5 ve 2 olmak üzere iki sayınız var ve toplamlarını üçüncü bir hücrede bulmak istiyorsunuz, diyelim ki A2. Bunu iki şekilde yapabilirsiniz.
Ya bu hücreye = 5 + 2 yazarak değerlerini A2 hücresine ileterek . Bu durumda, A1 veya B1 hücrelerinin değerleri değişirse, A2'deki toplam aynı kalır.
Veya = A1 + B1 yazarak A1 ve B1 hücrelerinin "referanslarını" A2 hücresine aktararak . Bu durumda, A1 veya B1 hücrelerinin değerleri değişirse, A2'deki toplam da değişir.
Değere göre iletme belirttiğiniz değişkende saklanan verilerin bir KOPYASINI gönderir, referansla iletme değişkenin kendisine doğrudan bir bağlantı gönderir. Bu nedenle, bir değişkeni başvuru ile iletir ve sonra geçirdiğiniz bloğun içindeki değişkeni değiştirirseniz, orijinal değişken değiştirilir. Yalnızca değere göre iletirseniz, orijinal değişken, ilettiğiniz blok tarafından değiştirilemez, ancak arama sırasında içerdiği her şeyin bir kopyasını alırsınız.
Değere göre ilet - İşlev değişkeni kopyalar ve bir kopyayla çalışır (böylece orijinal değişkendeki hiçbir şeyi değiştirmez)
Referansla ilet - İşlev orijinal değişkeni kullanır, diğer işlevdeki değişkeni değiştirirseniz, orijinal değişkende de değişir.
Örnek (bunu kendiniz kopyalayın ve kullanın / deneyin ve görün):
#include <iostream>
using namespace std;
void funct1(int a){ //pass-by-value
a = 6; //now "a" is 6 only in funct1, but not in main or anywhere else
}
void funct2(int &a){ //pass-by-reference
a = 7; //now "a" is 7 both in funct2, main and everywhere else it'll be used
}
int main()
{
int a = 5;
funct1(a);
cout<<endl<<"A is currently "<<a<<endl<<endl; //will output 5
funct2(a);
cout<<endl<<"A is currently "<<a<<endl<<endl; //will output 7
return 0;
}
Basit tut, dikizlemek. Metin duvarları kötü bir alışkanlık olabilir.
Aralarındaki en büyük fark, değer tipi değişkenlerin değerleri depolamasıdır, bu nedenle bir yöntem çağrısında bir değer tipi değişken belirtmek, bu değişkenin değerinin bir kopyasını yönteme iletir. Başvuru türü değişkenleri nesnelere başvuruları depolar, bu nedenle bağımsız değişken olarak başvuru türü değişkeni belirtmek, yönteme nesneye başvuran gerçek başvurunun bir kopyasını iletir. Başvurunun kendisi değere göre iletilse de, yöntem yine de aldığı başvuruyu orijinal nesneyle etkileşimde bulunmak ve muhtemelen değiştirmek için kullanabilir. Benzer şekilde, bir yöntemden bir return ifadesi aracılığıyla bilgi döndürürken, yöntem, bir değer türü değişkeninde depolanan değerin bir kopyasını veya bir başvuru türü değişkeninde depolanan başvurunun bir kopyasını döndürür. Bir başvuru döndürüldüğünde, çağıran yöntem başvurulan nesneyle etkileşimde bulunmak için bu başvuruyu kullanabilir. Yani,
C # 'da, çağrılan yöntemin değişkeni değiştirebilmesi için bir değişkeni başvuru yoluyla iletmek üzere C #, ref ve out anahtar sözcüklerini sağlar. Ref anahtar sözcüğünü bir parametre bildirimine uygulamak, bir değişkeni yönteme referans olarak geçirmenizi sağlar; çağrılan yöntem, arayandaki orijinal değişkeni değiştirebilir. Ref anahtar sözcüğü, çağıran yöntemde zaten başlatılmış olan değişkenler için kullanılır. Normalde, bir yöntem çağrısı bağımsız değişken olarak başlatılmamış bir değişken içeriyorsa, derleyici bir hata oluşturur. Out parametresi ile bir parametrenin önüne bir çıkış parametresi oluşturur. Bu, derleyiciye argümanın çağrılan yönteme başvuru ile aktarılacağını ve çağrılan yöntemin arayandaki orijinal değişkene bir değer atayacağını belirtir. Yöntem, olası her yürütme yolunda çıkış parametresine bir değer atamazsa, derleyici bir hata oluşturur. Bu, derleyicinin bir yönteme bağımsız değişken olarak iletilen başlatılmamış bir değişken için hata iletisi oluşturmasını da önler. Bir yöntem, bir return deyimi aracılığıyla arayanına yalnızca bir değer döndürebilir, ancak birden çok çıkış (ref ve / veya out) parametresi belirterek birçok değer döndürebilir.
bkz. c # tartışma ve örnekler burada bağlantı metni
Örnekler:
class Dog
{
public:
barkAt( const std::string& pOtherDog ); // const reference
barkAt( std::string pOtherDog ); // value
};
const &
genellikle en iyisidir. İnşaat ve yıkım cezasına çarptırılmazsınız. Referans sabit değilse, arayüzünüz iletilen verileri değiştireceğini önerir.
Orijinal değişkenin değerini bir işleve ilettikten sonra değiştirmek istemiyorsanız, işlev " by by value " ile oluşturulmalıdır. " parametresiyle oluşturulmalıdır.
Daha sonra işlev SADECE değere sahip olur, ancak iletilen değişkenin adresi olmaz. Değişkenin adresi olmadan, işlevin içindeki kod, işlevin dışından görüldüğü gibi değişken değerini değiştiremez.
Ancak, işleve, değişkenin değerini dışarıdan görüldüğü gibi değiştirme yeteneği vermek istiyorsanız , referansla pass kullanmanız gerekir . Hem değer hem de adres (başvuru) iletilir ve işlevin içinde bulunur.
değere göre geç, bağımsız değişkenleri kullanarak değerin bir işleve nasıl iletileceği anlamına gelir. değere göre geçişte, belirttiğimiz değişkende depolanan verileri kopyalarız ve veriler kopyalanarak referans bcse ile geçişten daha yavaştır. kopyalanan verilerde orijinal verilerden etkilenmeyen değişiklikler yaparız. refernce veya pass by address ile doğrudan değişkene doğrudan bağlantı göndeririz. veya işaretçiyi bir değişkene geçirme. daha hızlıdır, daha az zaman harcanır
Aşağıda, by by value - pointer değeri - reference arasındaki farkları gösteren bir örnek verilmiştir :
void swap_by_value(int a, int b){
int temp;
temp = a;
a = b;
b = temp;
}
void swap_by_pointer(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void swap_by_reference(int &a, int &b){
int temp;
temp = a;
a = b;
b = temp;
}
int main(void){
int arg1 = 1, arg2 = 2;
swap_by_value(arg1, arg2);
cout << arg1 << " " << arg2 << endl; //prints 1 2
swap_by_pointer(&arg1, &arg2);
cout << arg1 << " " << arg2 << endl; //prints 2 1
arg1 = 1; //reset values
arg2 = 2;
swap_by_reference(arg1, arg2);
cout << arg1 << " " << arg2 << endl; //prints 2 1
}
“Referans yoluyla geçme” yönteminin önemli bir sınırlaması vardır . Bir parametre başvuru ile iletildi olarak bildirilirse (öncesinde & işaretinden önce gelir) karşılık gelen gerçek parametresi bir değişken olmalıdır .
“Değere göre geçti” biçimindeki parametreye atıfta bulunan gerçek bir parametre genel olarak bir ifade olabilir , bu nedenle sadece bir değişkeni değil, aynı zamanda bir değişmezi, hatta bir işlev çağırma sonucunu da kullanmasına izin verilir.
İşlev, değişken dışında bir şeye değer koyamaz. Bir değişmeze yeni bir değer atayamaz veya bir ifadeyi sonucunu değiştirmeye zorlayamaz.
Not: Dylan Beattie'nin cevabını mevcut mesajda düz kelimelerle açıklayan olarak da kontrol edebilirsiniz.