C++

2010-04-10 3 views
5

'da bir başvuru döndürme double& ve string& döndürdüğüm aşağıdaki kodu dikkate alın. Bir çifte durumunda iyi çalışır, ancak bir ip durumunda olmaz. Davranış neden farklı? Ben bir başvuru dönen olarakC++

her iki olgu derleyici bile Warning: returning address of local variable or temporary atmaz.

#include <iostream> 
#include <string> 
using namespace std; 


double &getDouble(){ 
    double h = 46.5; 
    double &refD = h; 
    return refD; 
} 

string &getString(){ 
    string str = "Devil Jin"; 
    string &refStr = str; 
    return refStr; 
} 

int main(){ 
    double d = getDouble(); 
    cout << "Double = " << d << endl; 

    string str = getString(); 
    cout << "String = " << str.c_str() << endl; 

    return 0; 
} 

Çıktı:

$ ./a.exe 
Double = 46.5 
String = 
+0

Benzer bir gönderiim vardı ve cevaplar çok yardımcı oldu. Ayrıca, işlevle ilgili http://stackoverflow.com/questions/2612709/why-does-this-object-wonk-out-get-deleted – brainydexter

cevap

15

olursa olsun derleyici yapar veya yapmaz ne yerel değişkene başvuru döndürmek asla. Derleyici kolayca kandırılabilir. Kodunuzun doğruluğunu ateşlememiş olabilecek bazı uyarılara dayandırmamalısınız.

burada ateş etmedi sebebi muhtemelen tam anlamıyla yerel bir değişkene bir başvuru dönen değiliz ki, yerel bir değişkene bir referanstır bir değişken dönüyor. Derleyici muhtemelen bu biraz daha karmaşık durumu algılamaz. Sadece gibi şeyler algılar:

string &getString(){ 
    string str = "Devil Jin"; 
    return str; 
} 

muhtemelen algılama konusunda daha iyi bir iş yaptı yapılandırılması ve bu durumda bu yüzden derleyici akış kontrolü analizini karmaşık nesneyi tahrip içermez çünkü ikizi durum daha basittir Hata. Bir double için

+0

yorumlarına göz atın, açıkçası demek istiyorsunuz. kapsamınız dışındaki herhangi bir şeye bir başvuru göndermeye izin verilir: üye verileri, referans olarak alınan işlev parametreleri vb. – wilhelmtell

+6

Aslında, ikilinin durumunda bile uyarının DEVAM EDİLDİĞİNİ söyledi. Yani derleyici her iki durumda da aldatıldı. Çifte çalışmanın nedeni büyük olasılıkla yığındaki h'nin yerini yazmamış olması. Bunu deneyin: ana mağazada d çift & sonra diğer birkaç fonksiyonu arayın, sonra d yazdırın. Bahse girerim doğru çıkmaz. Her halükarda, yaptığınız şey "tanımlanmamış davranış" dır. Orada mükemmel bir ders var: sadece doğru cevabı vermesi doğru yoldan yapılması anlamına gelmez. ;) –

6

referans fiziksel olarak hala bellekte ama artık yığında bir konuma gelir. Sadece onunla uzaklaşıyorsunuz çünkü hafıza henüz yazılmamış. double bir ilkel olsa da, string bir nesnedir ve iç dizgiyi kapsam dışı kaldığında sıfır uzunluğuna temizleyebilen bir yıkıcıya sahiptir. Aramanızdan c_str() numarasına çöp almamanız bunu destekliyor gibi görünüyor. Bir uzantıyı için kullanılan

+1

Dürüst olmak gerekirse, tüm bunlar spekülasyon gibi görünüyor ve gerçekten önemli değil. Bir yerel değişkene bir başvuru döndüğünüzde derleyicinin istediği her şeyi yapmasına izin verilir.Bir mola vermek ve mutfak bir sandviç yapmak için gitmek gibi geliyorsa o zaman standart tarafından da iyi. Yani cevap basit: Değişkenin işleve yerel olmadığı sürece bir referans göndermeyin. – wilhelmtell

+0

Bu yüzden "ondan kurtulmak" dedim. Davranışı sadece "neden" diye cevaplamaya çalışmıyorum. –

+0

@wilhelmtell: Bu spekülasyon değil, ne olacak. Sorun, her şeyden önce kötü şeyler olabileceğinden, geri dönüş değerini kullanmanızdır: gerçekleşmesi gereken en iyi şey programınızın segmentasyonudur; En kötüsü, programın gizemli bir şekilde yanlış davranışlar göstermesine ya da daha sonra segfault'lara kadar çalışmaya devam etmesidir. – CMircea

1

GCC aynı şeyi başarmak izin Named Returns aradım ama fonksiyonu dışında yer ayırdı. Maalesef artık mevcut değil; Neden aldıklarını anlamadım

+0

+1. Ve SO'ya hoş geldiniz. –

0

C++ ile ilgili bir Dangling referansının klasik durumu Geriye dönük referanslar, koruma işaretlerini ayarlamak için derleyiciyi çağırmaya girişirken, çağrı yığınında değildi. Dize, derleyicinizin senaryoyu gözden kaçırmasına izin veren açık Çöp Toplama mekanizmasına sahiptir.