2012-03-22 33 views
2

取這兩個類如:讓本地變量引用其他局部變量有危險嗎?

struct Owned { 
    Owned() : i() { } 

    void print() { cout << ++i << endl; } 

    int i; 
}; 

struct Owner { 
    Owner(Owned& o) : o(o) { } 

    Owned& o; 

    ~Owner() { o.print(); } 
}; 

它是危險的這種方式來使用它們呢?

int main() { 
    Owned owned; 
    Owner owner(owned); 
} 

看來,這取決於它們的破壞,這可能導致owner析構函數來調用一個被毀壞的owned功能的順序。是否定義了銷燬局部變量的順序,以及如何處理兩個實例互相引用的情況?

請原諒我,如果這是常識,我還沒有讀過關於它的任何地方。

回答

5

局部變量按照與創建相反的順序銷燬。在你的情況下,你很好,因爲owner將永遠銷燬owned之前。

§6.6 [stmt.jump] p2

在從範圍(但是完成)退出,與已經構建在範圍在其構造的相反的順序被破壞自動存儲持續時間(3.7.3)對象。

但是,如果您可以在施工後重新分配擁有的成員,則必須小心。

你怎麼能讓兩個實例互相引用工作?

不要讓它們在析構函數中互相訪問。或者先清楚究竟誰會被首先銷燬,也許會有一個回調或標誌被通過。例如:

struct two; 
struct one{ 
    two* other; 

    one(two* o = nullptr) : other(o) {} 
    ~one(){ if(other) other.other = nullptr; } 
}; 

struct two{ 
    one* other; 
    two(one* o = nullptr) : other(o) {} 
    ~one(){ if(other) other.other = nullptr; } 
}; 

這將確保兩個對象從不引用不存在的引用。

相互引用的對象是非常罕見的。

+0

好吧,這基本上是我在想什麼。謝謝。 – 2012-03-22 17:38:27

+0

通過「讓兩個實例互相引用」我假定你的意思是'擁有'和'所有者'都包含對立類型的成員引用。這樣做,你不能真的。但那是因爲引用不能在創建後重新分配給新的對象。如果你只是a)切換到指針,b)在構造函數之外執行任務(將你從特定的時間問題中解脫出來),那麼你可以完全掌握什麼可以達到什麼目的。但具有很大的權力....:p – 2012-03-22 17:43:39

+0

@邁克爾:只需分配給建設後的「其他」成員。我已經有指針了。 '一個o;兩個t(&o); o.other =&t;' – Xeo 2012-03-22 17:44:40

0

這是安全的,本地對象以創建它們的相反順序銷燬。

+0

那麼如果我以另一種方式聲明他們,行爲是不確定的?那麼第二個問題呢? – 2012-03-22 17:29:32

+0

@SethCarnegie:你如何以另一種方式宣佈他們? – Naveen 2012-03-22 17:32:54

1

Owner實際上並不擁有owned它只是有一個引用它,所以當它被銷燬的時候,擁有的析構函數將不會被調用。

+0

這忽略了問題的關鍵。 – 2012-03-22 17:30:10

+0

擔心的是'擁有'將在'所有者'之前被銷燬,因此後者的析構者將訪問一個懸而未決的參考。 – Xeo 2012-03-22 17:30:18

+0

對不起,沒睡過 – 111111 2012-03-22 17:37:15

1

無論如何,你寫的東西並不危險,C++中相同範圍內的變量會以定義的(反向排序的方式)被銷燬。然而,像這樣的事情是危險的,但是,

int main() { 
    Owner owner(); 
    { 
     Owned owned; 
     owner.setOwned(owned); 
    } 

    owner.doSomethingWithOwned(); 
} 

因爲擁有不再存在,它被迫超出範圍。這也適用於將局部變量設置爲堆中對象的引用。

+0

函數沒有名爲'setOwned'的方法:) – 2012-03-22 17:35:55

+0

你是對的。但是,如果您將setOwned圖像以類似的方式複製到構造函數中,您可以看到不應該引用超出範圍的對象(因爲它不存在)。 – 2012-03-22 17:46:05

+0

是的,除了函數聲明外,答案是正確的(AFAIK)。 – 2012-03-22 18:02:16