2017-02-09 60 views
3

假設我有這樣的代碼: -C++:如何在循環內創建一個對象在棧中工作?

struct myStruct{ 

    int a; 
    int b; 
}; 

int main(){ 

    for(int i=0; i<5; i++){ 

     myStruct obj; 
     cout<<"Address of object in memory : "<<&obj<<endl; 
    } 

    return 0; 
} 

,這實際上在棧上創建了5個不同的對象?如果是這樣,爲什麼每次考慮到obj是實際的對象而不是對象的引用時,它會打印出完全相同的內存地址?我在網站上閱讀了一些答案,但我仍然無法完全理解。

+1

它爲每一個重複使用相同的空間,這就是爲什麼你看到相同的地址 –

+2

* Stack *是一個實現細節(編譯器實現)。它不是由C語言標準決定的(甚至沒有定義什麼是堆棧)。因此,每個編譯器供應商都可以自由選擇。 –

回答

1

對象obj在每次迭代開始時創建,並在最後銷燬。

如果將輸出語句放在其構造函數和析構函數中,您將能夠看到發生的情況。 (儘管在技術上,編譯器可以自由地刪除對象,如果檢測它們存在的唯一方法是跟蹤構造函數和析構函數調用,大多數編譯器可能不會在這種情況下,因爲替代方案將在開始時重新初始化對象每次迭代)。

您也可以通過添加一個額外的範圍來看到這一點。

int main() 
{ 

    for(int i=0; i<5; i++) 
    { 
     { // extra scope here 
      myStruct obj; 
      cout<<"Address of object in memory : "<<&obj<<endl; 
     } 
     obj = something(); // will not compile since obj does not exist here 
    } 

    return 0; 
} 

與使用堆(一個實現細節,而不是由標準所要求的)編譯器,有一個公平的機會,額外的變量將不會被置於一次迭代的結束和開始之間的堆棧上下一個。這將解釋你看到所有的對象具有相同的地址。

2

如果您打印出的地址相同,則意味着內存空間被重用,並不意味着它們是相同的對象。

如果添加一個用戶定義的構造(和析構函數),你會看到5個不同的對象構造(和析構):

struct myStruct{ 

    myStruct() { std::cout << "ctor\n"; } 
    ~myStruct() { std::cout << "dtor\n"; } 

    int a; 
    int b; 
}; 

可能的結果:

ctor 
Address of object in memory : 0x7fffc5be8c50 
dtor 
ctor 
Address of object in memory : 0x7fffc5be8c50 
dtor 
ctor 
Address of object in memory : 0x7fffc5be8c50 
dtor 
ctor 
Address of object in memory : 0x7fffc5be8c50 
dtor 
ctor 
Address of object in memory : 0x7fffc5be8c50 
dtor 

LIVE

0

這是否實際上創建了5個不同的對象在堆棧上

是的,它確實創建了5個不同的對象。它是否在堆棧上創建它是另一回事。 它所說的是,在for循環的每次迭代中,靜態地創建一個新對象。現在,靜態創建對象時,它具有預定義的作用域和生命週期,這在編譯時本身決定。例如myStruct obj;範圍是for循環。無論您在每次迭代中是否獲得相同或不同地址的實例,都是實現定義的。

另外,每個對象都有自己的標識,可以通過它們是新創建(如其他答案中指定的)的事實來驗證它。另外,這個標識由對象的範圍,生命週期,名稱的組合來定義。現在,這個標識不能是該對象的地址。