2011-08-16 46 views
4

A const int *int *const是非常不同的。與const std::auto_ptr<int>std::auto_ptr<const int>相似。然而,似乎沒有這樣的區別const std::vector<int>std::vector<const int>(實際上我不確定第二個甚至被允許)。爲什麼是這樣?爲什麼std :: vector將其常量傳遞給包含的對象?

有時我有一個函數,我想傳遞一個向量的引用。該函數不應該修改向量本身(例如,否push_back()),但它希望修改每個包含的值(比如增加它們)。同樣,我可能想要一個函數只改變向量結構,但不修改任何現有的內容(儘管這很奇怪)。這種事情是可能的std::auto_ptr(例如),但由於std::vector::front()(例如)被定義爲

const T &front() const; 
T &front(); 

,而不是僅僅

T &front() const; 

有沒有辦法來表達這一點。什麼我想要做

例子:

//create a (non-modifiable) auto_ptr containing a (modifiable) int 
const std::auto_ptr<int> a(new int(3)); 

//this works and makes sense - changing the value pointed to, not the pointer itself 
*a = 4; 
//this is an error, as it should be 
a.reset(); 


//create a (non-modifiable) vector containing a (modifiable) int 
const std::vector<int> v(1, 3); 

//this makes sense to me but doesn't work - trying to change the value in the vector, not the vector itself 
v.front() = 4; 
//this is an error, as it should be 
v.clear(); 
+1

我沒有看到有人提到過這個,但是一個const的指針向量允許你改變指針所指向的對象,並且可以在需要時用作解決方法。 –

回答

7

這是一個設計決策。

如果您有一個const容器,通常有理由認爲您不希望任何人修改它包含的元素,而這些元素是其內在的一部分。如果你願意,容器完全「擁有」這些元素「鞏固了這種聯繫」。

這與歷史的,更低級別的「容器」實現(即原始數組)相比更爲放手。正如你所說的那樣,int const*int * const之間有很大的區別。但標準容器只需選擇通過const即可。

+0

我認爲這是有道理的,它只是讓我覺得奇怪的是,有些容器(對於這個問題我認爲'std :: auto_ptr'是一個容器),而其他容器則不這樣做。它似乎打破了「如有疑問,按照整體做」的一般理念。 – Karu

+0

@Karu:如果你想考慮'std :: auto_ptr'是一個容器,那麼這是你的選擇......但這並不改變它不是這樣的事實。 :) –

4

不同的是,指針爲int沒有自己的整數它們指向,而vector<int>並擁有包含整數。 A vector<int>可以被概念化爲int成員的結構,其中成員的數量恰好是可變的。

如果你想創建一個函數,可以修改矢量中包含的值,但不是矢量本身,那麼你應該設計函數來接受迭代器參數。

例子:

void setAllToOne(std::vector<int>::iterator begin, std::vector<int>::iterator end) 
{ 
    std::for_each(begin, end, [](int& elem) { elem = 1; }); 
} 

如果你能負擔得起把所需的功能在頭,那麼就可以進行通用性:

template<typename OutputIterator> 
void setAllToOne(OutputIterator begin, OutputIterator end) 
{ 
    typedef typename iterator_traits<OutputIterator>::reference ref; 
    std::for_each(begin, end, [](ref elem) { elem = 1; }); 
} 
1

句法上與您的建議是一個大問題是這樣的:a std::vector<const T>是不是與std::vector<T>類型相同。因此,您無法將vector<T>傳遞給預計不需要某種轉換的vector<const T>的函數。不是一個簡單的演員,而是創建一個新的vector<const T>。而這個新人不能簡單地與老人分享數據;它將不得不將數據從舊數據複製或移動到新數據。

你可以用std::shared_ptr弄到這個,但那是因爲那些是共享指針。您可以有兩個對象引用相同的指針,因此從std::shared_ptr<T>shared_ptr<const T>的轉換不會影響(超過引用計數)。沒有這樣的東西,如shared_vector

std::unique_ptr也可以使用,因爲它們只能被移動,不能被複制。因此,他們中只有一個會有指針。

所以你要求的是根本不可能的。

+0

你不能有'std :: vector '。元素類型必須是可複製和可分配的。乾杯&hth。, –

+0

@Alf:我知道std :: vector如何工作。提問者問爲什麼它不能以另一種方式工作,其中std :: vector 實際上會起作用。 –

+0

通過從const專門化派生non-const可能是有點可能的:http://ideone.com/BYOnl。最大的問題是缺乏我們不希望的**標準**容器的虛擬析構函數(但是如果您要設計容器,我想它可以)。任何其他可能的問題? – visitor

1
  • 你是正確的,不可能有一個const int向量,主要是因爲元素將不可賦值(對vector中包含的元素類型的要求)。
  • 如果你想要一個只修改一個向量元素但不向元素添加元素的函數,這主要是STL爲你做的 - 具有不知道哪個容器包含一個元素序列的函數。該函數只需要一對迭代器併爲該序列完成它的事情,完全忽略了它們包含在向量中的事實。
  • 查找「插入迭代器」以瞭解如何將某些東西插入到容器中而無需知道元素是什麼。例如,back_inserter需要一個容器,它所關心的只是知道該容器有一個名爲「push_back」的成員函數。
相關問題