2011-08-05 69 views
3

這與a question posted yesterday有關。延長對象生命週期的C++ const引用成員

class A 
{ 
public: 
    mutable int x; 
    A() 
    { 
     static int i = 0; 
     x = i; 
     i++; 
     std::cout << " A()" << std::endl; 
    } 
    ~A() 
    { 
     std::cout << "~A()" << std::endl; 
    } 
    void foo() const 
    { 
     x = 1; 
    }; 
}; 

class B 
{ 
public: 
    const A & a; 
    B(const A & a) : a(a) 
    { 
     std::cout << " B()" << std::endl; 
    } 
    ~B() 
    { 
     std::cout << "~B()" << std::endl; 
    } 
    void doSomething() 
    { 
     a.foo(); 
    }; 
}; 

int main() 
{ 
    B b((A())); 
    b.doSomething(); 
} 

現在,在調用doSomething之前調用析構函數。然而,雖然函數基本上改變了A的一個成員,但是這個調用起作用。它不是同一個實例。沒有其他A被創建。我使用A的構造函數中的靜態來跟蹤它。誰能解釋一下?

+0

Luchian的空間不能與那些...重用:我添加了鏈接到昨天的問題。希望你指的是我的問題。 – Nawaz

+0

是的,正好:) –

回答

6

這是未定義的行爲,所以沒有語言標準的解釋。

但是,A的析構函數對存儲區域的存儲區域沒有任何影響,所以如果稍後再看,值可能仍然存在。或者如果您嘗試寫入地址,地址仍然存在。你不能這樣做。

+0

這就解釋了它。謝謝! –

0
  • 你參考〜A(後無效),它是不確定的行爲
  • 〜A()調用A的所有成員的析構函數除了

嘗試如此例如

class B 
    { 
    public: 
      const std::string & a; 
      B(const std::string & a) : a(a) 
      { 
        std::cout << " B()" << std::endl; 
      } 
      ~B() 
      { 
        std::cout << "~B()" << std::endl; 
      } 
      void doSomething() 
      { 
        std::cout << "a = " << a << std::endl; 
      }; 
    }; 

    int main() 
    { 
      B b(std::string("I love C++ so much!")); 
      b.doSomething(); 
    } 
0

博是正確的。另外,你可以檢查存儲'A'的地址,並且應該確認這個地址還沒有被重用(記住析構函數釋放(「釋放」)內存,但是不會不會遍歷數據結構,將所有的位設置回0;這將是低效的)。

例如,如果您發現A存儲在堆棧頂部,那麼您很幸運,您的後續函數調用不會傳遞參數,因爲這會覆蓋A的內存區域。

0

擴大博的答案。

對於臨時存在,空間將被保留在堆棧上。這個空間實際上是保留的,只要語義要求臨時存在,然後可以重用於其他事物。

如果你在重用它後試圖使用內存,你會觀察到一個奇怪的行爲(非定義行爲的定義是任何事情都可能發生)。因爲它是,你運氣出和內存仍然存在,在你期望的狀態。

例子:

#include <iostream> 

struct A { 
    A(): p(0) {} 
    ~A() { if (p) { std::cout << *p << "\n"; } } 
    int* p; 
}; 

int bar0(); 
void bar1(int i); 

int main() { 
    A a; 
    { 
    int x = 4; a.p = &x; 
    } 
    { 
    int y = bar0(); bar1(y); 
    } 
} 

int bar0() { return 7; } 
void bar1(int i) { std::cout << i << "\n"; } 

這裏,編譯器可以選擇重用的x的空間y,或只是做任何它想做,這樣你實際上打印垃圾。

這裏是gcc 4.3.4(4.5.1和)輸出(ideone提供):

7 
4 

意思就是說