映射运算符 [] 的返回值(和"at"方法)

return value of map operator[] (and "at" method)

本文关键字:at 方法 返回值 运算符 映射      更新时间:2023-10-16

我有以下示例代码来解释我的问题。 根据 STD 映射容器文档 (http://www.cplusplus.com/reference/map/map/operator%5B%5D/),运算符 [](或"at"方法)返回对映射值的引用。 我明白为什么第 13 行编译并正常工作(当我将元素插入 vec1 时,map 中的映射值会更新)。 我不明白为什么第 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 }

我想也许 operator[] 的实际实现被重载以返回两种类型(值和引用)。 但是,当我浏览"map"头文件时,它似乎没有(除非我错过了什么):

文件 :/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   

有人可以帮我理解这一点吗?

类型通常可以从引用复制构造。所以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.

关于你对两种返回类型的假设,你不能通过返回值重载函数。

12 行将vec1初始化为对port[1]的引用(或者更准确地说,port[1]引用的vector<int>对象)。因此,对vec1的任何更改也会port[1]更改。

第 13 行将vec2初始化为 port[1] 的副本。因此,对vec2的任何更改都不会影响port[1]

不确定我是否正确理解了你的问题,所以,我将尝试用 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