2016-07-25 83 views
6

我對下面的C++代碼有點糊塗了:初始化

#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; 
} 

由於變量c被聲明爲staticconst,應該不是這個只進行一次初始化,並保持其初始值直到過程完成?根據這個道理,我期待下面的輸出:

Hello 
Hello 

但我得到:

Hello 
Nooo 

你能解釋,爲什麼變量c的價值已經過兩次功能之間修改調用,即使它是一個const變量?

回答

14

您的程序有未定義的行爲

當傳遞到"hello"test,則創建臨時std::string對象,並從該字符串c構造(這僅僅是一個指向字符串對象的數據)。

函數調用結束時,臨時std::string對象被銷燬,c成爲懸掛指針。再次使用它是未定義的行爲。

就你而言,第二個臨時對象的數據std::string與第一個對象的數據具有完全相同的內存地址,因此c指向該數據。這是不能保證的。

+0

其實它不是未定義的。 **解除引用**它是未定義的。由於它在解引用時總是有一個有效的地址,所以它是一個有效的程序。 – StoryTeller

+3

@StoryTeller,'cout << c << endl;'提供指針的引用。 –

+1

@StoryTeller輸出操作符使用解引用。 –

1

您的代碼中有未定義的行爲,因此這些結果可能會有所不同。 UB是因爲調用test("Hello");創建了一個臨時值,然後將其分配給靜態局部變量。這個臨時函數在調用結束後被刪除,所以測試函數中的指針是懸空的。如果你使用它,那麼你有未定義的行爲。

內存管理器有可能重用相同的內存區域,以便在結果中看到Hello和Nooo。