Call by value & call by reference

Selamlar

Bu konu hakkında yazılmış birçok makale var.Bende kendim daha iyi anlamak için kendi bloguma karalama tarzında bir yazı yazacağım.

Yazdığımız programlama dillerinde hepimiz fonksiyonlar/metodlar tanımlıyoruz. Bunlara parametre geçiyoruz bazen dönüş değeri olarak , bazen ise verdiğimiz parametreler üzerinde değişiklik yapıp sonucunu alıyoruz.

Programlama dillerinde, fonksiyonlar iki şekilde çağrılabilir: Call by Value ve Call by Reference.

Genelde fonksiyon method tanımlamalarınıza extra bildirmediğiniz sürece “reference by value” yaklamşımı kullanılır. Bizde ilk önce bunu bir örnek ile göreceğiz.

Call by value

Buraya kadar tamam. Normal şartlarda bu nasıl gerçekleşiyor basit bir örnek yapalım.İlk örneğimizde 2 değişkeni birbiriyle değiştiren klasik bir swap fonksiyonu yazcağız.Örneğimizi inceleyelim.

#include <stdio.h>


void swap(int a,int b) {
    int temp;
    temp = a;
    a = b;
    b = temp;
}

int main() {

    int a = 50 , b = 20;
    printf("a: %d \t b: %d \n",a,b);

    /* calling a function to swap the values */
    swap(a, b);

    printf("a: %d \t b: %d \n",a,b);

    return 0;
}

Yukarıdaki kodu incelersek standart bir swap fonksiyonumuz var. Ancak bunu çağırsak bile çıktı değişmiyor. a ve b değişkenlerimiz değerlerini koruyorlar.

metinagaoglu@linux-mint:~/Desktop/C/refs$ ./ref
a: 50 b: 20
a: 50 b: 20

Reference by value’da bir değişkenin değerini bufonksiyonun parametresine kopyalar. Bu nedenle, ana işlevin parametresinde yapılan değişiklikler bağımsız değişkeni etkilemez.Saddece fonkssiyonun içerisinde geçerliğidir.Aynı değerden memory’de 2 tane vardır. Parametre olarak geçilenler direk değerleri kopyalanmıştır.

Yaptığınız değişiklikler kopyalanan değerler üzerinde yapılır.Foksiyon dışındakiler etkilenmez.Fonksiyo çalıştıkran sonra kopya silinir ve memory’de sizin geçtikleriniz aynen duruyordur. Bu yüzden çıktılarımız aynı.

Call by Reference

Call by reference ta ise fonksiyona parametre olarak referencelarını geçiyoruz.Yani memory’de nerde olduklarını. Fonksiyonun içerisinde ise bu değerler ile memory’deki yerini bildiğimiz değişkendeki değerlerle gene istediğimiz işlemi yapabiliyoruz. Diğer yaklaşımdan farklı değerler kopyalanmadığı için yaptıklarınız her değişiklik değeri değiştiriyor.

Az önce yaptığımız swap fonksiyonunu şimdide call by reference ile yazalım.

#include <stdio.h>

void swap(int *a,int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}

int main() {

int a = 50 , b = 20;
printf("a: %d \t b: %d \n",a,b);

/* calling a function to swap the values */
swap(&a, &b);

printf("a: %d \t b: %d \n",a,b);


return 0;
}

Bu seferki durumda ise gördüğünüz gibi main içerisinde swap fonksiyonmuza & işareti ile referansını geçtik. İçeride ise parametre olarak geçilen değerin referansı ile memorydeki adresine ulaştık ve o değerler üzerinde işlem yaptık.

metinagaoglu@linux-mint:~/Desktop/C/refs$ ./ref
a: 50 b: 20
a: 20 b: 50

Tabiki biz bu yazıda gene kolayına kaçtık ve 2 integer değişkeni kullandık.Ancak örnekleri bununla sınırl tutmayın.Elimizde bir array veya linkedlist vs türünde büyük bir değer varsa ve bunu üzerinde işlem yapıcaksak şeklindede düşünebilirsiniz.

Ne olduğunu kabaca anladığımıza göre biraz avantaj ve dezavantajlarından bahsedelim.

Call by value avantajları

  1. Parametre olarak geçilen ana değişkenler değişmez.
  2. Takibatı ve debug yapması daha kolaydır.Ana değişkendeki değerleri değiştirmediği için fonksiyon içinde daha rahat geçici işlem vs yapılabilir.

Dezavantajları

  1. Hafıza açısından verimli değildir.Aynı değişken için oluşturulmuş iki adet kopya vardır..

Call by reference avantajları

  1. Fonksiyon argümanın değerini değiştirebilir.
  2. Bellek alanından tasarruf etmenize yardımcı olur. Tek bir değeri tutmak için yinelenen veriler oluşturmaz.
  3. Bu yöntemde işlem yapılan parametrenin bir kopyası yoktur. Bu nedenle çok hızlı işlenir.

Dezavantajları

  1. Referans alan bir fonksiyonunu parametresinin boş olmadığından emin olması gerekir.
  2. Çok iş parçacıklı programlarla çalışırken tehlikelidir.
  3. Takibatı ve debug’ı bi nebze daha zordur.

Göz atmanızı tavsiye ettiğim kaynaklar:

https://stackoverflow.com/questions/40185665/performance-cost-of-passing-by-value-vs-by-reference-or-by-pointer

https://www.geeksforgeeks.org/difference-between-call-by-value-and-call-by-reference/

https://www.guru99.com/call-by-value-vs-call-by-reference.html