2014-10-06 90 views
0

關於如何在C++中安全地傳遞和使用向量的快速問題。在C++中通過指針和引用傳遞向量

我知道,在使用矢量時,你必須非常小心地址給他們和他們的元素,因爲當你動態改變他們的大小時,他們可能會改變他們的地址(除非你使用預留等,但我想象着我不會知道我需要多少空間)。

現在我想通過一個現有的矢量(在其他地方創建)到一個函數來調整它並改變它的大小等,但我有點不清楚什麼是安全的,因爲我通常會實現所有這些與指針。最重要的是使用對矢量的引用,這只是爲我的泥水。

例如採取以下兩種職能和評論他們

void function1(std::vector<int>* vec){ 

    std::cout<<"the size of the vector is: "<<vec->size()<<std::endl; //presumably valid here 

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

     (*vec).pushback(i); //Is this safe? Or will this fail? 
     // Or: vec->pushback(i); Any difference? 
    } 

    std::cout<<"the size of the vector is: "<<vec->size()<<std::endl; //Is this line valid here?? 

} 

void function2(std::vector<int>& vec){ 

    std::cout<<"the size of the vector is: "<<vec.size()<<std::endl; //presumably valid here 

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

     vec.pushback(i); //Is this safe? Or will this fail? 

    } 

    std::cout<<"the size of the vector is: "<<vec.size()<<std::endl; //Is this line valid here?? 

} 

有兩個功能之間的任何差別,無論是在功能方面和在安全性方面?或者換句話說,如果我只有一個指向矢量的指針/引用,並且需要調整它的大小,我該如何確定矢量實際上在內存中的位置,或者指向矢量的指針真的在哪裏我操作它。謝謝。

+1

這兩個都是有效的。你必須小心處理的只是元素內**的地址**向量和迭代器。因此,如果你在內部執行了'int * foo =&vec [0]',然後'push_back'ed元素,那麼這個指針可能在之後無效。然而,無論矢量執行的操作如何,指向矢量的指針仍然有效。 – Xarn 2014-10-06 14:27:27

+0

一個向量管理它自己的內存,所有你必須擔心的是你傳入的*實例*。期望指針的函數對我來說意味着在使用它之前會檢查* pointee *是否有效,另一方面參考將不會做這樣的檢查。除了檢查,功能上他們是一樣的。 – Nim 2014-10-06 14:28:06

+0

好的,輝煌的,謝謝。所以我基本上混淆了向量與數組?就像在一個數組中,指向它的指針可以被認爲是指向第一個元素的指針,從中可以使用指針算術來訪問它的其餘部分。但是對於矢量而言,它是一個指向容器的指針,該容器是一些可能被該容器改變的連續內存的接口。 – user3353819 2014-10-06 14:31:47

回答

1

就功能而言,在您給予我們的非常有限的環境中,它們基本上是相同的。

在更普遍的看法,如果你想寫通用代碼,考慮到操作和運營商直接綁定到引用,而不是指針

a = b + c; 

編譯需要

A operator+(const B&, const C&); 

A* operator+(const B*, const C*); 

是一個不同的野獸。另外,一個採用引用和取值的表達式具有相同的語法,但採取指針的表達式需要指針提供相同的語義,但這會導致不同的表達式語法(*a + *ba+b),從而導致「較少通用代碼「。如果你正在編寫一個具有運行時多態性的類(以及腦中的lyskov替換),那麼你很可能會對待動態分配的對象,因此,通過指針操縱它們可能更自然。

存在兩個東西網格化的「灰色區域」,但是在基於運行時的OOP框架中,通用指針捕捉函數更頻繁,而「基於值的泛型算法」中參考捕捉函數更頻繁,其中靜態預計會出現類型扣除,並且最有可能需要基於堆疊的分配。