Forum: Diğer Konular RSS
C++ Explicit ve Kopya Kurucu Fonksiyonu
İbrahim #1
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: C++ Explicit ve Kopya Kurucu Fonksiyonu
Selam;
Ben C++'da şöyle bir kod yazdım:
class Counter
{
private:
    int count;
public:
    Counter() : count(0)
    {
    }
 
    Counter(int count) : count(count)
    {
    }
 
    int to_int() const
    {
        return count;
    }
 
    void print() const
    {
        cout << count << endl;
    }
};
 
void do_stuff(Counter counter)
{
    int c = counter.to_int();
    cout << "c = " << c << endl;
}
 
int main()
{
    Counter c0(7);
    c0.print();
    do_stuff(17);
    
    return 0;
}

Bu kodda explicit anahtar kelimesini kullanmadığım için parametreyi ve do_stuff fonksiyonunu kandırabiliyorum.
do_stuff fonksiyonuna argüman olarak direk 17 geçiriyorum ve program çalışıyor. Bunu explicit ile engelleyebilirim, fakat explicit de kullanmadan koda şu kurucu fonksiyonu yazdığımda:
class Counter
{
...
    Counter(Counter& count) : count(count.count)
    {
    }
...
};
do_stuff fonksiyonunu kandıramıyorum. Artık do_stuff(17) çalışmıyor. Benim anlamadığım nokta ise int parametre alan Counter kurucu fonksiyonu varken neden alakasız bir kurucu fonksiyon ile explicit koymadan hata veriyor?
Ama bu kurucu fonksiyonun parametresini const Counter& count olarak değiştirdiğimde yine program kanarak çalışıyor. Bu kurucu fonksiyon nasıl etkiliyor bu do_stuff'ı?

Teşekkürler!
acehreli (Moderatör) #2
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
int'ten Counter oluşturan ifade bir sağ değerdir:

  http://ddili.org/ders/d/deger_sol_sag.html

C++'ta sağ değerler yalnızca 'const&' parametrelere bağlanabilirler. (D'de ona da bağlanamazlar.)

Derleyicinin tanımladığı otomatik kopyalayıcı sağ değerlerle bile kullanılabilsin diye 'const&' parametre alır. Burada programcının kopyalayıcısı const olmayan referans aldığından, int'ten Counter'a dönüşümün sağ değeri o parametreye bağlanamıyor.

Ali
İbrahim #3
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Cevabınız için teşekkürler Ali Hocam.
Kurucu fonksiyon şu şekilde: Counter::Counter(Counter& count) : count(count.count) {}
Eğer doğru anladıysam direk 17 atamak sağ değer olduğu için ve parametre const olmadığı ve referans olduğu için hata verdiğini söylediniz. Bu halde o zaman direk 17 atamak yerine int value = 17; deyip sonra do_stuff(value); diye atamak gerekir diye bir düşünce oluştu bende, fakat bunu deneyince de çalışmadı. Halbuki value referans olarak geçebilir dediğinize göre çünkü value bir sol değer oluyor.
Bir de anlamadığım ben do_stuff'a apaçık bir int değeri giriyorum fakat Counter(int count) dururken niye Counter(Counter& count) kurucu fonksiyonuna bakıyor?
Bu arada verdiğiniz linkteki yazıyı okudum ve sol, sağ değer kavramlarını kavramaya çalıştım.

Teşekkürler!
acehreli (Moderatör) #4
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Tabii, burada kopyalayıcının 'const Counter&' alması gerektiği biliyoruz, değil mi? Böylece sağ değerleri ve const değişkenleri de kabul edebiliriz.

İbrahim:
Counter::Counter(Counter& count) : count(count.count) {}

Onun sorunu, parametresinde değişiklik yapabilecek gibi göründüğünden ne const değişkenlerle ne de sağ değerlerle kullanılabilir.

direk 17 atamak sağ değer olduğu için

Doğru ama buradaki sorun 17 sağ değeri ile değil, otomatik olarak oluşturulan Conuter(17) sağ değeri ile ilgili. Eğer işlev 'int&' alsaydı ve 17 geçirmeye çalışsaydı o zaman sorun 17 sağ değeri ile ilgili olurdu.

direk 17 atamak yerine int value = 17; deyip

Yukarıdakine bağlı olarak, Counter value(17); dersen çalışır.

Bir de anlamadığım ben do_stuff'a apaçık bir int değeri giriyorum fakat Counter(int count) dururken niye Counter(Counter& count) kurucu fonksiyonuna bakıyor?

Derleyici şöyle düşünüyor: do_stuff Counter istiyor ama 17 veriyoruz. int alan ve explicit olmayan bir kurucu olduğuna göre onu kullanabiliriz. Tamam...

Ama dur bir dakika! do_stuff aslında parametresini kopyalayarak alıyor. Tamam, o zaman elimizdeki Counter(17) sağ değerini kopyalayalım. Ah! Ne yazık ki Counter'ın kopyalayıcısı aldığı parametreyi değiştirmek istiyor. Kullanamayız. Pardon... :)

Bu arada verdiğiniz linkteki yazıyı okudum ve sol, sağ değer kavramlarını kavramaya çalıştım.

O konuda hâlâ soru işareti var mı?

Sağ değerleri isimsiz geçici değerler olarak düşünmek kolay: Geçici ifade olduğuna göre işlemcinin bir yazmacında bile yaşayabilir ve dolayısıyla adresi yoktur. Yani, bellekte yer tutmayabilir. O yüzden adresi alınamaz, vs.

Ali
İbrahim #5
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
do_stuff aslında parametresini kopyalayarak alıyor. Tamam, o zaman elimizdeki Counter(17) sağ değerini kopyalayalım.
Çok teşekkürler. Aslında benim sorunum fonksiyonların parametreleri kopya olarak almasını sadece yüzeysel olarak bilmemmiş. Fonksiyon parametreyi değer olarak alıyor ve bu da kopyalamak demek ama nasıl? Hiç aklıma Counter(17) gibi gelmemişti :). Zannediyorum ki kopyalaması Counter c(17) gibi, ama meğersem geçici olarak kopyalamaymış :).
Tekrardan teşekkürler.
İbrahim #6
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Fakat bir dakika, eğer fonksiyon Counter(17) gibi kopyalıyorsa şu nasıl oluyor?:
void do_stuff(Counter counter)
{
    counter = 5;
    int c = counter.to_int();
    cout << "c = " << c << endl;
}
 
int main()
{
    do_stuff(17)// Çıktı: 5
 
    return 0;
}
Burada counter = 5; yapıyoruz, halbuki Counter(17) diye kopyalandı yani geçici olarak. Bu şu ifade demek değil mi? : Counter(17) = 5;
Bu ifade yanlış değil midir? Nasıl oluyor?
Teşekkürler!
agora #7
Üye Tem 2013 tarihinden beri · 221 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Sağ değerlerin işlemcide yaşadığını ilk defa öğrendim.

Her sağ değer işlemcide mi yaşar peki?
acehreli (Moderatör) #8
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
agora:
Her sağ değer işlemcide mi yaşar peki?

Onu durumu açıklamak için örnek olarak söyledim. Yoksa aslında her değer (ve değişken) derleyicinin eniyileştirmelerine bağlı olarak hiç bellekte yaşamayabilir.

Ama bir sol değerin adresi alındığı an derleyici onun için bellekte yer ayırmalıdır. (Aslında o bile eniyileştirmelere göre gerekmeyebilir.) Öte yandan, sağ değer için böyle bir şey yok: Adresi bile alınamaz. Buna rağmen, derleyici isterse sağ değeri bile geçici olarak belleğe, örneğin yığıta koyabilir.

Ali
acehreli (Moderatör) #9
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #5
İbrahim:
kopyalaması Counter c(17) gibi, ama meğersem geçici olarak kopyalamaymış

Özetle, do_stuff(17) ifadesinden sonra işlev içindeki counter şu ifade ile edinilmiş gibi oluyor:
Counter counter(Counter(17))

Yani, önce 17'den bir sağ değer ediniliyor, sonra o parametreye kopyalanıyor.

Burada counter = 5; yapıyoruz, halbuki Counter(17) diye kopyalandı

Sağ değer olan yalnızca Counter(17). İşlev içindeki counter ise bir sol değer ve başlıbaşına bir değişken. Bu kodda işlev içindeyken sağ değerle hiçbir işimiz kalmamış durumda.

Ali
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-19, 06:08:22 (UTC -08:00)