2010-03-01 40 views
6

我有一個類,產生任意數量的工人對象,計算他們的結果到std::vector。我將在某些點刪除一些工作對象,但我想保留他們的結果,只按照spawned他們知道的那個類別。因此,我爲類A中的輸出提供了向量。我有(IMO)三個選項:我可以指向矢量,引用或迭代器作爲成員。雖然迭代器選項有一定的退步(迭代器可以遞增)。我不確定指針或引用是否更清晰。 我覺得引用更好,因爲它們不能爲NULL,並且要求存在一個向量。迭代器與參考與指針

我最不確定的是參考文獻的有效性。 std::list< std::vector<int> >上的某些操作會使其失效嗎?這些操作是否與使std::list的迭代器無效相同?有沒有另外一種方法我現在沒有看到?此外,與容器的耦合感覺不對:我強制將一個特定的容器加入到Cruncher類中。提供爲清楚起見

代碼:

#include <list> 
#include <vector> 
#include <boost/ptr_container/ptr_list.hpp> 

class Cruncher { 
    std::vector<int>* numPointer; 
    std::vector<int>& numRef; 
    std::list< std::vector<int> >::iterator numIterator; 
public: 
    Cruncher(std::vector<int>*); 
    Cruncher(std::vector<int>&); 
    Cruncher(std::list< std::vector<int> >::iterator); 
}; 

class A { 
    std::list< std::vector<int> > container; 
    boost::ptr_list< std::vector<int> > container2; 
    std::vector<Cruncher> cruncherList; 
}; 

回答

6
如果

迭代器被無效,它也將無效的指針/參考迭代器被轉換成。如果你有這樣的:

std::vector<T>::iterator it = ...; 
T *p = &(*it); 
T &r = *p; 

如果迭代器失效(例如調用的push_back可以無效所有現有的矢量迭代器),指針和引用也將失效。

從標準23.2.4.2/5(矢量容量):

注:重新分配無效的所有引用,指針和迭代器指的是序列中的元素。

對於std :: list,同樣的一般原則也適用。如果迭代器失效,迭代器轉換成的指針和引用也失效。

std :: list和std :: vector之間的區別是導致迭代器失效的原因。只要不刪除它所指的元素,std :: list迭代器就是有效的。因此,如果std::vector<>::push_back可以使迭代器無效,則std::list<>::push_back不能。

+0

我打算使用std :: list來存儲指向對象的指針樣品。如果您只是將標準的報價更改爲解釋列表失效的部分,則您的答案沒問題。 – pmr

+0

@pmr - 更新了我的答案,以包含更多關於列表的信息。 –

1

如果在產生工作線程後重新分配父代的向量內容,那麼它們的指針,引用,迭代器或其他什麼都是幾乎肯定是無效。列表可能不同(給定它們如何分配),但我不知道,甚至可能取決於平臺。

基本上,如果你有多個工作線程,那麼在父類上實際上有一個方法可以將結果轉儲回來,只要這個副本不是那種賦稅就可能是最安全的。當然,它不如直接分配給父母,但是你需要確保你傾倒的容器在重新分配時不會「丟失」。

如果您使用的列表保證不會在成員添加(或刪除)時重新分配其「其他」空間,那麼這將實現您正在尋找的內容,但該矢量絕對是不安全的。但無論哪種方式,只要您的「根容器」不會圍繞其內容移動,您訪問它的方式(指針,引用或迭代器)可能無關緊要。

編輯:

如在下面的評論中提到,這裏是從SGI's website(重點煤礦)對列表中的塊:

列出有 插入和拼接不 的重要財產使迭代器無效以列出元素, 並且即使刪除也只會使指向已刪除元素的 元素的迭代器僅失效 。的 排序的迭代器可以改變 (即目錄::迭代器可能 的確要比之前 列表手術後不同的前置或後續 ),但迭代器本身 不會失效或製成 指向不同元素,除非 表示無效或突變爲 顯式。

因此,這基本上是說「使用一個列表作爲您的主存儲」,然後每個工人可以轉儲到自己的,並知道它不會失效時,另一個工人完成,他們的載體從名單。

+0

只要當前指向的元素未被擦除,列表迭代器仍然有效。 – James

+0

你說得對,自動填充。作者可以在關於列表的段落中參考http://stackoverflow.com/questions/1436020/c-stl-containers-whats-the-difference-between-deque-and-list/1436038#1436038。 – fogo

+0

@fogo:謝謝,我編輯了我的OP,添加了SGI網站上的文字。 –

0

在C++的當前版本(即無移動構造函數)中,指向嵌入在std :: list中的項的指針將與列表迭代器一起失效。

如果你使用了std :: list *>,那麼vector *可以移動,但vector不會,所以你的指向vector的指針將保持有效。

隨着C++ 0x中的移動構造函數的增加,矢量內容可能會保持放置狀態,除非矢量本身被調整大小,但是任何這樣的假設本質上都是不可移植的。

0

我喜歡指針參數。這是一個風格問題。我更喜歡這種參數類型風格:

  • 強制參考:大對象正在傳遞閱讀。參考避免了浪費的複製。看起來就像在通話點傳遞值。
  • 指針:讀取對象並編寫。該電話將有一個「&」來獲取指針,因此在代碼審查期間寫作變得明顯。
  • 非常量引用:禁用,因爲代碼審查無法確定哪些參數可能會作爲副作用發生更改。

正如你所說,迭代器在父容器類型上創建了一個無意義的依賴關係。 (std :: list被實現爲一個雙鏈表,所以只有刪除它的入口才會使向量無效。所以它會起作用。)

+1

將非常量引用與指針進行比較時,副作用有何區別?除了在另一個地方提及另一個&符號之外,我沒有看到任何其他的東西。 – pmr

+0

當函數被調用時,非const引用看起來完全像傳遞值,但允許函數更改參數。這意味着閱讀代碼的人必須閱讀每個函數的所有文檔,以正確地知道函數可能會發生什麼變化。用我描述的風格,你可以閱讀一個調用,並知道沒有符號的參數不會被改變,而有可能的參數將被改變。這對於大型軟件的正式代碼評審可能有幫助。 –

+1

如果您還沒有閱讀函數的文檔,則不應該調用它。編輯:你確定不應該審查它。 –