2011-04-19 123 views
9
class Node 
{ 
public: 

    Node *parent; // used during the search to record the parent of successor nodes 
    Node *child; // used after the search for the application to view the search in reverse 

    float g; // cost of this node + it's predecessors 
    float h; // heuristic estimate of distance to goal 
    float f; // sum of cumulative cost of predecessors and self and heuristic 

    Node() : 
      parent(0), 
      child(0), 
      g(0.0f), 
      h(0.0f), 
      f(0.0f) 
    { 
    } 

    UserState m_UserState; 
}; 

爲什麼我們應該使用構造我應該使用初始化程序列表還是在我的C++構造函數中執行賦值?

Node() : 
      parent(0), 
      child(0), 
      g(0.0f), 
      h(0.0f), 
      f(0.0f) 
    { 
    } 

,而不是

Node() 
    { 
     parent = null; 
     child = null; 
     g = 0.0f; 
     h = 0.0f; 
     f = 0.0f; 
    } 

謝謝:)

回答

14

對於普通的舊數據(POD),這有什麼好處,但一旦你開始使用參考文獻或組成課程,它會產生變化:

class Foo { 
    Bar bar; 

    public: 
    // construct bar from x 
    Foo(int x) : bar(x) { } 
}; 

Foo::Foo(int x) 
{ 
    // bar is default-constructed; how do we "re-construct" it from x? 
    bar = x; // requires operator=(int) on bar; even if that's available, 
       // time is wasted default-constructing bar 
} 

有時候,你甚至不會有「重新構建」的方式,一旦已建成,作爲一類可能不支持制定者或operator=的對象。 const成員可以肯定不會被「重新構建」或復位:

class FooWithConstBar { 
    const Bar bar; 

    public: 
    Foo(int x) { 
     // bar is cast in stone for the lifetime of this Foo object 
    } 
}; 

編輯:感謝@Vitus與參考指出的問題。

+0

啊,你寫過我的時候更新了關於常量的帖子。我真的厭倦了「西部最快的槍」綜合徵。 – rjnilsson 2011-04-19 10:57:08

+3

也不能在構造函數的正文中分配引用,並且必須在初始化程序列表中進行初始化。 – Vitus 2011-04-19 12:44:04

2

主要是因爲性能問題。

這是討論here

1

主要原因是對象有效性和類不變量。另一個原因是易用性。

如果你把所有的東西都放在構造函數中,那麼當構造函數完成時你保證有一個有效的節點。 如果必須單獨設置所有實例變量,那麼可能會讓某個節點的某些變量未初始化,因爲程序員忘記了或者其中一個賦值引發了異常。後者不會發生在你的情況下,但總的來說可以。如果節點沒有完全初始化,它的行爲不能保證如你所期望的那樣。

6

因爲有一些情況下,您實際上需要或性能方面的原因應該使用初始化列表初始化成員,你應該一致並始終使用它。

需要使用初始化列表的示例是聚合沒有默認構造函數或有const成員時(yes,uncommon,但允許)。

就是當你應該(但不強制)的例子中使用初始化列表是當你有一個聚合對象和以下幾點是有效的:

  • 的總有一個默認的構造函數。
  • 您需要設置非默認值的對象。
  • 聚合具有一個構造函數,它允許您設置所需的非默認值。

現在,然後 - 爲什麼你不應該使用它?

+1

我可以想到完全人爲的情況下,你想兩個對象的初始化順序是不同的,這取決於構造函數的一些標誌。 '如果(a){b = new X(NULL); c =新Y(b); } else {c = new Y(NULL); b = new X(c); }'。即使以示例形式,它對我來說也不好 - 但它不能通過初始化列表完成。 – 2011-04-19 11:44:31

+0

@Joe:你能想出一個不涉及資源分配的例子嗎?如果在成員init列表的初始化期間拋出一個異常,那麼行爲是很好定義的,但在這個例子中,你必須編寫相當多的代碼來保證內存被正確釋放,如果X,Y或對'new'的調用會引發異常。 – 2011-04-19 18:22:55

+0

(+1)如果在成員初始化列表中初始化期間拋出異常,那麼可能需要包含有關保證的信息。 – 2011-04-19 18:25:20

相關問題