使用临时程序将迭代器获取到STL容器时的细微错误:如何避免
Subtle error when using temporaries to get iterators to a STL container: how to avoid it?
让我们考虑一下这个类:
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 1
和Statement 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
类存在一些严重的设计问题:
_map
应该更好地封装在类中(用于读和写访问),因此可以避免使用getTheMap()
方法- 如果确实需要
getTheMap()
方法,它可以返回对_map
的引用
然而,给定类X"原样"(<--请参阅下面的编辑),有没有办法防止用户将迭代器获取到临时迭代器?
EDIT:类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
这可以防止像地图一样意外地使用临时的,但会使其成为用户必须使用地图副本的地方。
不在C++03中。在C++11中,标准库应该已经启用了这种保护。
您可以尝试使用std::move强制getTheMap()返回原始对象,但我不确定这在这里是否有效。
如果没有,我想返回成员的唯一/shared_ptr将是最好的选择。
相关文章:
- 如何确保在使用基于布尔值的两个方法之一调用方法时避免分支预测错误
- 避免模板类中的重定义错误
- 避免指针运算,修复叮当整齐错误
- 如何避免分段错误
- 试图避免在 for 循环中出现 if-else 语句,但代码似乎有一些错误
- 如何避免具有相同类型参数的函数中的错误
- 如何避免指针超出范围(多态性)的C++分段错误
- 使用N-API时如何避免分段错误
- 如何避免 boost 的野兽body_limit错误并正确处理大消息
- 避免错误共享以提高性能
- 如何修复我的字符串以避免运行时错误?
- C++模板 - 使用"std::is_same_v"而不是专用并避免编译错误?
- 当 PHP、C++ 和 shell 脚本尝试访问同一个文件时,如何避免错误?
- C++ 获取线错误。如何避免此错误?"没有重载函数"getline"的实例
- 如何避免出现分段核心转储错误?
- C++:避免"use of deleted function"错误
- 如何避免浮点格式错误
- 需要"override"案例时重叠模板部分专用化:如何避免错误?
- 如何避免错误:在抛出 what() 的实例后终止调用'std::logic_error':basic_string::_S_construct null 无效
- 读取文件时避免错误标志