【问题标题】:C++ map element doesn't get erased if I refer to it如果我引用它,C++ 地图元素不会被删除
【发布时间】:2013-06-11 04:18:06
【问题描述】:

玩弄 C++ 标准库的 std::map 类,并注意到如果我删除一个元素,然后尝试引用它(下面代码中注释掉的行),该元素将返回值为 0。这是预期的吗?如果元素不存在,您真的必须使用 find 函数来访问元素而不意外创建吗?

编译器设置:我正在使用 g++ i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1(基于 Apple Inc. build 5658)在 osx 10.8.3 上编译(LLVM build 2336.11.00)

using namespace std;

map<int,int> myMap;
map<int,int>::iterator it;

myMap[1] = 5;

for (it=myMap.begin(); it!=myMap.end(); ++it)
    std::cout << it->first << " => " << it->second << '\n';

printf("map test result: %d\n", myMap[1]);

it = myMap.find(1);
myMap.erase( it );

// If I uncomment this it will cause a 0 value to occur at key 1.
//printf("map test result: %d\n", myMap[1]);

if (myMap.find(1) == myMap.end())
    puts("element key 1 is null, ok");
else
    puts("element @ key 1 exists, error");

if (myMap.empty())
    puts("map is empty");
else
    puts("map is not empty, error");

for (it=myMap.begin(); it!=myMap.end(); ++it)
    std::cout << it->first << " => " << it->second << '\n';

澄清一下,如果我在第二个 printf 行注释的情况下运行它,它会按预期运行:

1 => 5
map test result: 5
element key 1 is null, ok
map is empty

如果我在未注释行的情况下运行,则在 printf 语句中访问 myMap[1] 会创建另一个元素,并留下以下结果:

1 => 5
map test result: 5
map test result: 0
element @ key 1 exists, error
map is not empty, error
1 => 0

【问题讨论】:

    标签: c++ map std


    【解决方案1】:

    是的,这是 operator[]std::map 应该做的。来自标准(C++11,§23.5.4.3):

    mapped_type& operator[](const key_type& k);
    mapped_type& operator[](key_type&& k);
    

    [...]

    效果:如果 unordered_map 不包含 key 等于 k ​​的元素,则第一个运算符插入值 value_type(k, mapped_type()),第二个运算符插入值 value_type(std::move(k), mapped_type())

    请注意,即使元素从未被插入然后被删除,也会发生这种情况。使用 operator[] 进行元素访问时,只需将其应用于不存在的键时,它会插入新的、默认构造的值。

    如果你不想这样,最好使用std::mapfind 函数。如果键不存在,这将返回一个end-iterator。

    【讨论】:

      【解决方案2】:

      是的,这是预期的行为。除了阅读规范之外,您还可以从类型签名中推断出这一点:

      T& operator[] (const key_type& k);
      

      它无法判断您是否最终会分配给该键,因为在 [] 运算符已经完成执行之后,在其返回值上调用了 operator =。该方法也无法表示空值:它返回的是引用,而不是指针。

      【讨论】:

      • +1(尽管理论上,地图可以返回对某种虚拟元素的引用。这是一种奇怪的设计,但并非不可能)。
      • 它现在的工作方式使其非常适合容器的计数器或地图。 map[key]++ 或 map[key].push_back(value) 比不这样做的语言(如 java)中的等价物要干净得多
      • @jogojapan 确实!这当然可以通过查看T 是否与您在std::map&lt;T&gt; 中提供的T 来检查。
      猜你喜欢
      • 1970-01-01
      • 2016-03-09
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多