2016-07-25 35 views
6

Aşağıdaki C++ kodu hakkında biraz karıştı:Başlatma

#include <iostream> 

using namespace std; 

void test(const string& str) 
{ 
    static const char * const c = str.c_str(); 
    cout << c << endl; 
} 

int main(int argc, char* argv[]) 
{ 
    test("Hello"); 
    test("Nooo"); 
    return 0; 
} 

değişken c yana static ve const olarak ilan edilir, bu yalnızca bir kez başlatılır edilmemelidir ve başlangıç ​​değerini tutmak süreç tamamlanana kadar? Bu mantığa göre, aşağıdaki çıktıyı bekliyordum:

Hello 
Hello 

Ama var: değişken c değeri iki fonksiyonu arasındaki değiştirildi neden

Hello 
Nooo 

Eğer açıklık getirebilir bile olsa çağrıları const değişkeni nedir?

cevap

14

Programınızda tanımlanmamış davranış var.

Eğer test için "hello" geçmesi

, geçici std::string nesne oluşturulur ve bu dizge c den (String nesnesi verilerine sadece bir işaretçi olduğu) yapılmıştır.

İşlev çağrısı sona erdiğinde, std::string geçici nesnesi yok edilir ve c sarkan bir işaretçi olur. Bunu tekrar kullanmak tanımlanmamış bir davranıştır.

Sizin durumunuzda, ikinci geçici std::string nesnenin verileri, ilk verileriyle aynı bellek adresine sahiptir, bu nedenle c bu verilere işaret eder. Bu hiçbir şekilde garanti edilemez. Kodunuzda Tanımsız Davranışınız var, bu nedenle bu sonuçlar farklılık gösterebilir.

+0

Aslında tanımsız değil. ** Dereferencing ** tanımlanmamıştır. Dereferans edildiğinde her zaman geçerli bir adrese sahip olduğundan, geçerli bir programdır. – StoryTeller

+3

@StoryTeller, cout << c << endl; 'işaretçiyi işaret eder. –

+1

@StoryTeller Çıktı operatörü dereferansı kullanır. –

1

UB, test("Hello"); numaralı aramanın geçici bir yerel oluşturduğundan geçici yerel bir değişken oluşturduğundan dolayıdır. Bu geçici bir çağrı sona erdikten sonra desent edilir, bu nedenle test fonksiyonundaki işaretçi sarkıtılır. Eğer kullanırsanız, tanımlanmamış davranışınız vardır.

Bellek yöneticisinin aynı bellek bölgesini yeniden kullanması mümkündür, böylece sonuçlarınızda Hello ve Nooo'yu görürsünüz.