2013-10-24 18 views
2

我有以下示例代碼來解釋我的問題。根據STD地圖容器doc(http://www.cplusplus.com/reference/map/map/operator%5B%5D/),運算符[](或「at」方法)返回對映射值的引用。我明白了爲什麼第13行編譯並正確工作(當我將元素插入到vec1中時,映射中的映射值得到更新)。我不明白爲什麼第13行不會導致編譯錯誤,因爲vec1不是引用,運算符[]返回引用。返回值映射運算符[](和「在」方法)

1 #include <map> 
    2 #include <vector> 
    3 
    4 using namespace std; 
    5 
    6 int main() 
    7 { 
    8  map<int, vector<int> > port; 
    9 
10  port[1] = vector<int>(1, 10); 
11 
12  vector<int> &vec1 = port[1]; // <=== 
13  vector<int> vec2 = port[1]; // <=== 
14 
15  return 0; 
16 } 

我想也許是運算符[]的實際實現被重載以返回兩種類型(值和參考)。然而,當我通過「地圖」頭文件看,它似乎沒有(除非我失去了一些東西):

文件:/usr/include/c++/4.7/profile/map.h

 // 23.3.1.2 element access: 
     mapped_type& 
     operator[](const key_type& __k) 
     { 
     __profcxx_map_to_unordered_map_find(this, size()); 
     return _Base::operator[](__k); 
     } 

#ifdef __GXX_EXPERIMENTAL_CXX0X__ 
     mapped_type& 
     operator[](key_type&& __k) 
     { 
     __profcxx_map_to_unordered_map_find(this, size()); 
     return _Base::operator[](std::move(__k)); 
     } 
#endif 

有人能幫我理解嗎?

+0

但'vec1' *是一個參考。 – juanchopanza

+0

對不起,我的意思是第13行,其中vec2不是參考。 (我糾正了我原來的問題)。 –

回答

6

類型通常可從參考中複製構建。所以vec2只是拷貝port[1]返回的引用所引用的值。這是一個簡單的例子,涉及ints

int i = 42; 
int j& = i; // j is a reference to i 
int k = j; // k is a copy of the int that j refers to, i.e. i. 

關於你有關這兩個返回類型的假設,你不能返回值重載函數。

+0

謝謝。你的解釋和進一步閱讀「C++可複製構造」澄清了發生了什麼以及爲什麼。 (HTTP://www.cplusplus。com/reference/type_traits/is_copy_constructible /) –

+0

我意外地遇到了這個問題,忘記把&當我宣佈vec類型(如第13行),並花了我一段時間來找出問題。這似乎是一個容易犯的錯誤,並帶來嚴重的後果。有沒有辦法讓我可以打開一些編譯器選項來給出這種事件的警告。 –

+0

@AhmedA我懷疑任何編譯器都會發出警告,因爲它是完全合法的。通常不會將引用綁定到返回值。典型的用例是做'post [1] .push_back(42)'等等。 – juanchopanza

2

第12行初始化vec1是對port[1](或更確切地說,port[1]所指的vector<int>對象)的引用。所以任何改變vec1也改變port[1]

第13行初始化vec2拷貝port[1]。因此,對vec2的任何更改都不會影響port[1]

2

不知道我是否正確理解了你的問題,所以我只是試着向你解釋12和13行是怎麼回事。

vector<int> &vec1 = port[1]; 

在這裏,你要創建一個參考的載體,並與port[1]初始化。所以,實際上,他們現在指向相同的內存位置。

vector<int> vec2 = port[1]; 

在這裏,你正在創建一個新的矢量port[1]所有的數據複製到其中。它們包含相同的數據,但它們不指向相同的內存位置。

所以,如果你能做到這一點:

vec1.push_back(1); 
vec2.push_back(2); 

你會看到,現在port[1]包含一個新的附加元素 - 1