2010-12-15 71 views
1

我有一類的容器(含指針)作爲成員:如何返回一個const std :: vector <Object * const>?

MyClass{ 
private: 
    std::vector<MyObject*> _VecMyObjs; 
public: 
    const std::vector<MyObject* const> GetVecMyObj(); 
} 

現在我嘗試實施GetVecMyObj()。以下是我想出了...

const vector<MyObject *const> ACI_CALL MyClass::GetVecMyObjs() 
{ 
    const vector<MyObject *const> VecMyObjs; 
    VecMyObjs.assign(_VecMyObjs.begin(), _VecMyObjs.end()); 
    return VecMyObjs; 
} 

但當然編譯器警告我,說我使用分配功能的一個const-對象。有一個更好的方法嗎?我的意思是,當然,我不希望VecMyObjs在課堂外改變VecMyObj。如何在沒有編譯器警告的情況下實現該目標?編輯: 好的。謝謝大家。現在是這樣的:

const vector<MyObject *const> ACI_CALL MyClass::GetVecMyObjs() 
{ 
    const vector<MyObject *const> VecMyObjs; 
    VecMyObjs.assign(_VecMyObjs.begin(), _VecMyObjs.end()); 
    return VecMyObjs; 
} 

但是,我無法繞過分配函數,對吧?例如。如果我想讓「一切」保持不變,那麼鑄造「原創」是行不通的。

+4

你不需要VicMyObjs是GetVecMyObjs函數內部常量......返回時,該資格將被隱式添加。 – 2010-12-15 11:14:42

+0

您確定要使用vector 而不使用vector 嗎?爲什麼通過引用返回const不可行? – Palmik 2010-12-15 11:30:12

+0

關於你的編輯,你希望一切都是恆定的:正如其他人已經指出的,你正在使指針爲const,而不是指向的對象。這些可以改變,從而改變你的內部對象。 – stefaanv 2010-12-15 11:54:25

回答

3

我不知道std::vector<MyObject * const>(恆定指針矢量)真的是你想要的東西:我相信你的意思是std::vector<MyObject const *>(指向常量對象的向量)。

  1. 常量性(指針常量性)的「第一級」自然是通過返回對向量恆定的參考來實現。只有const_iterator可以從一個const向量中獲得,所以你可以保證指針不會被修改(但pointees可以)。

  2. 常量的「第二級」(10 pointee常量)很難獲得。要麼返回向量的一個新的實例作爲已經指出別人:

    return std::vector<const MyObject *>(_VecMyObjs.begin(), _VecMyObjs.end()); 
    

    或者,如果適用,試圖尋找到Boost Pointer Container庫(最引人注目的是ptr_vector)它提供,除其他事項外,正確的常量性傳播:

    傳播常量性,使得一個 不能通過 常量性修改的對象。

您要明白,返回上一個矢量保證它不能被修改const引用(無插入,缺失,或它的值的修改)。所以,在大多數情況下,返回一個const std::vector<T> &是要走的路,因爲如果不涉及任何複製。這裏的問題實際上是指向容器的特定對象,其中值的常量不提供pointees的常量。

+0

謝謝,我知道有這樣的事情......也許我應該開始另一個問題線程,但是「std :: vector 和「const vector then?還是一樣? – AudioDroid 2010-12-15 12:12:05

+1

@AudioDroid:no:你可以修改一個非常量向量('push_back','erase',...),而你不能修改一個const向量(從某種意義上說,它只提供只讀訪問到已經存儲的元素)。但是,關於元素*的常量*,它們提供了相同的保證。 – icecrime 2010-12-15 12:18:09

+0

太好了。謝謝!如果你可以仔細檢查我自己的答案....我希望我完全理解你。 – AudioDroid 2010-12-15 12:33:52

2

如果你想返回一個新的vector,不要使它const。將const關鍵字放在*之前。

std::vector<MyObject const*> MyClass::GetVecMyObj() 
{ 
    return std::vector<MyObject const*>(_VecMyObjs.begin(), _VecMyObjs.end()); 
} 

我省略了轉換TRoadSgmt因爲你沒有指定這個類的繼承。

+0

糟糕,[TRoadSgmt]並不打算在這個一般的例子中。我只是糾正它。 – AudioDroid 2010-12-15 11:34:26

0

除了將簽名刪除從vectorconst(因爲它是載體的拷貝),我假設你不想外面的人來修改的內容,因此,做一個const指針,即

vector<const MyObject *> ACI_CALL MyClass::GetVecMyObjs() 
{ 
    return vector<const MyObject *>(_VecMyObjs.begin(), _VecMyObjs.end()); 
} 

現在返回向量的副本,其中包含常量指針(這意味着你不能修改通過該指針所指向的對象) - 阱是這樣的協議,沒有什麼阻止他人const_cast是荷蘭國際集團這就是(反正使用UB!)

如果您確實想要阻止修改,請返回向量中的副本(或每個對象的克隆)。

+0

「VecMyObjs」聲明中的'const'關鍵字出錯。 – 2010-12-15 11:24:56

+0

我雖然語法「常量矢量,可確保‘向量的內容’(在這種情況下:所有的指針MyObjects)!不斷 – AudioDroid 2010-12-15 11:29:42

+0

@larsmans - 教我要盲目照搬THX,固定@AudioDroid,我不這麼認爲,它不僅使'VECTOR'對象不變,我不相信有什麼它擁有的任何擔保.. – Nim 2010-12-15 11:40:33

0
const vector<const MyObject *> MyClass::GetVecMyObjs() const 
{ 
    return vector<const MyObject *>(_VecMyObjs.begin(), _VecMyObjs.end()); 
} 

這似乎是對我的解決方案。我現在可以告訴我,得到所有不同的帖子。 謝謝大家!有一個很好的一個... (或者讓我知道,如果我還是錯的地方。)

+0

你是返回一個新的載體的實例,所以在使返回的矢量常量是沒有意義的(這是一個副本,無論如何,爲什麼你會介意調用者'push_back'的東西呢?) – icecrime 2010-12-15 12:32:03

+1

@icecrime:在一個臨時對象上調用一個變異操作很可能是一個錯誤,返回一個'const'對象會捕獲客戶端代碼凱斯是一個不正確的假設,也許他們正在參考。防止'clz.GetVecMyObjs()。push_back(x)'可能是一件好事。返回一個const對象不會阻止返回值的正常拷貝,例如'vector cpy = clz.GetVecMyObjs(); cpy.push_back(X);'。 – 2010-12-15 12:46:42

+0

@Charles Bailey:你是對的,那是我沒有考慮的東西 – icecrime 2010-12-15 12:48:07

1

假設非const指針的向量駐留在整個生命週期中的某個地方,您將使用const版本,因此您不需要副本,並且如果有很多這樣的指針,想要複製矢量,最好返回一些自定義的包裝對象,只給用戶const-access。

向量的第一個元素的地址將是T **,你不能強制轉換爲const T **(正確),也可以將它轉換成const T * const的*(這將是安全的,但該語言不允許它)。

如果你被允許後者將是完美的轉換創建只讀視圖。

相關問題