2011-09-14 51 views
2
矢量

考慮下面的類:投STL ::包含指向STL ::含載體常指針

class SomeInfo 
{ 
private: 
    std::vector<someObj *> _myVector; 

public: 
    const std::vector<const someObj*>& getInfoVector() const 
    { 
     return _myVector; 
    } 
}; 

當我嘗試用gcc 4.1.2編譯,它給了我下面的錯誤:

error: invalid initialization of reference of type 
‘const std::vector<const someObj*, std::allocator<const someObj*> >&’ 
from expression of type 
‘const std::vector<someObj*, std::allocator<someObj*> > 

如果我刪除'someObj *'前的'const',然後編譯,但我不想用非常量指針返回向量,因爲我不想讓它們引用的對象從我的SomeInfo類外部改變。在這個情況下,你會怎麼做?

+1

爲什麼不首先使_myVector成爲常量指針的向量? – Ferruccio

+0

因爲在後面階段,會有一個析構函數,它必須'刪除'常量指針,我知道這是允許的語言,但我認爲它很醜陋!從我的觀點來看,const是const的,不應該被觸及......這個向量成員不是這種情況,它不是const,我只是想讓const訪問它的值。 – pinpinokio

回答

3

我會在這種情況下做的是忘記返回一個vector(或引用)。調用者不能進行任何更改,因此不需要查看任何特定的容器。其他答案解釋了爲什麼你不能把你的向量看作是向量const someObj*。對於這個問題,如果將來您將班級更改爲使用deque而不是vector,那麼您無法返回對此的引用,就好像它也是一個向量。由於主叫方只需要訪問的元素,讓我們給他們說:

const someObj *getInfoAt(size_t n) const { 
    return _myVector.at(n); 
} 

const_info_iterator getInfoBegin() const { 
    return _myVector.begin(); 
} 

const_info_iterator getInfoEnd() const { 
    return _myVector.end(); 
} 

size_t getInfoSize() const { 
    return _myVector.size(); 
} 

// plus anything else they need. 

const_info_iterator是一個typedef的一類是有點煩寫​​。它必須包裝一個std::vector<someObj *>::const_iterator並且規定operator*的類型。 boost::transform_iterator可能是有用的,或從零開始編寫並不是那麼糟糕。不過,雙向迭代器確實需要最多的運算符重載。

std::vector<const someObj*> mycopy(myinfo.getInfoBegin(), myinfo.getInfoEnd()); 

什麼他們不能有一個vector,不斷反映:現在

,如果主叫方真正想要的const someObj*,向量然後用我的界面,他們可以很容易地在任何特定時刻得到一個快照其他vector其他地方的變化 - std::vector只是不這樣做。

+0

謝謝,史蒂夫,也許你的方法最符合我的需求。你是對的,因爲我的類的用戶不會被允許改變我給他的數據結構,爲什麼我應該給整個數據結構......只需使用一組訪問器來公開這個結構的元素緩解他的生活。 – pinpinokio

0

std::vector<T*>std::vector<const T*>不是相同的類型。你怎麼能這樣寫:

std::vector<T*> obj(100); 
std::vector<const T*> & ref = obj; //error 

這就是你在做你的代碼,這是無效的。您可以創建一個類型的引用,以引用其他類型的對象。

那麼試試這個:

std::vector<const someObj*> getInfoVector() const 
{ 
    return std::vector<const someObj*>(_myVector.begin(), _myVector.end()); 
} 

現在,它返回它包含指針從原來的向量臨時載體。此外,請注意,退貨類型爲而不是參考了。

+0

只是好奇,但爲什麼'返回值的const'? (還要注意,返回一個副本不像返回一個對真實事物的引用一樣的語義。) –

+0

@James:是的。這不是必需的。 – Nawaz

+0

返回值中的指針上的const是,所以沒有人可以改變這些指針指向的對象的值。感謝Nawaz,你所說的解釋了這種情況,但是如果我返回一個矢量副本,它會使程序變得太慢,所以我買不起(速度對我的應用程序至關重要)。 – pinpinokio

0

你可以寫getInfoVector這樣的:

std::vector<const someObj*> getInfoVector() const 
{ 
    std::vector<const someObj*> obj; 
    std::copy(_myVector.begin(), _myVector.end(), std::back_inserter(obj)); 
    return obj; 
} 
+0

是的,這是行得通的,但同樣會對性能產生嚴重影響......我不想給我的矢量用戶提供特殊的新結構,我只是想保護他免於做愚蠢的事情。 – pinpinokio

0

What would you do in this situation?

作爲替代其他的答案,這裏是一個簡單的方法,它不需要複製或分配:

const someObj* SomeInfo::getSomeObjAt(const size_t& idx) const { 
    return this->_myVector.at(idx); 
} 

甚至更​​好許多情況下,只是SomeInfo 而不是公開它的內部。

+0

謝謝,賈斯汀,這看起來很不錯,第一個答案 - >「不要給你的數據結構訪問,只有它的元素」 – pinpinokio

+0

大概,你指的是史蒂夫傑索普的答案作爲第一個答案:我的答案已發佈2 (他的回答完全是對我的第一點的更詳細的描述)。我的第二點也非常重要。更詳細地說,這意味着'SomeInfo'通常應該是對其'somObj'進行操作的,而不是將它們提供給客戶端。 – justin