c++ - 使用临时对象将迭代器获取到 STL 容器时出现细微错误 : how to avoid it?

标签 c++ stl iterator temporary-objects

让我们考虑一下这个类:

class X {
    std::map<uint32_t, uint32_t> _map;
public:
    X() { /* Populate the map */ }

    std::map<uint32_t, uint32_t> getTheMap() { return _map; }
};

还有这个有问题的代码:

X x;
// Statement 1
std::map<uint32_t, uint32_t>::const_iterator it = x.getTheMap().begin();
// Statement 2
std::map<uint32_t, uint32_t>::const_iterator et = x.getTheMap().end();

for (; it != et; it++) {
    /* Access the map using the iterator it */
}

错误的部分是,在 Statement 1Statement 2 中,我得到了一个指向临时对象的迭代器,该对象将在每一个陈述。 因此,for() 循环内的行为是未定义的。

getTheMap() 方法的正确用法应该是这样的:

std::map<uint32_t, uint32_t> map = x.getTheMap();
std::map<uint32_t, uint32_t>::const_iterator it = map.begin();
std::map<uint32_t, uint32_t>::const_iterator et = map.end();

for (/* [...] */)

必须注意类 X 有一些严重的设计问题:

  1. _map 应该更好地封装在类中(读写访问),因此可以避免 getTheMap() 方法
  2. 如果确实需要 getTheMap() 方法,它可以返回对 _map 的引用

但是,如果“按原样”给定 X 类(<-- 请参阅下面的编辑),是否有办法阻止用户将迭代器获取到临时值?

编辑:类 X 可以更改,但 getTheMap 方法应该存在并按值返回。但是我也在考虑编译器警告。

最佳答案

一种可能是使用这样的包装器:

class X {
  typedef std::map<uint32_t,uint32_t> Map;
  Map _map;

  struct MapWrap {
    const Map &mapref;

    MapWrap(const Map &mapref_arg)
    : mapref(mapref_arg)
    {
    }

    operator Map() const { return mapref; }
  };


public:
  MapWrap getTheMap()
  {
    return MapWrap(_map);
  }
};

所以你得到这个:

X x;
std::map<uint32_t,uint32_t>::const_iterator iter = x.getTheMap().begin(); // error
std::map<uint32_t,uint32_t> m = x.getTheMap(); // no error

这可以防止意外使用像 map 这样的临时文件,但会使其成为用户必须使用 map 拷贝的地方。

关于c++ - 使用临时对象将迭代器获取到 STL 容器时出现细微错误 : how to avoid it?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9806094/

相关文章:

c++ - 用于快速查找的最佳 STL 容器

python - Python 中的 zip 对象不是迭代器吗?

c++ - STL风格算法: how to manage output iterator

python - 如何使用 lldb 调试 C++ pybind11 模块?

c++ - C++:在子类中扩展静态STL容器/映射成员?

c++ - 什么库包含 map STL 集合?

c++ - STL 中有解引用迭代器吗?

c++ - Qt qtableWidget 单元格颜色

c++ - 运算符重载类型转换错误

c++ - 如何将用户输入的数据从 datagridview 获取到 Windows 窗体图表?