为什么要对 map::find 应用不存在的键将返回一个C++中第一个值映射大小的迭代器
Why apply a non-exist key to map::find would return a iterator with first value map size in C++?
我有一个像下面的代码片段这样的用例,在getter返回的map中使用map::find
来查找不存在的键实际上会找到一个迭代器,第一个值是map的大小(可能),因此不会按预期运行,等于map::end
这可能是因为我的地图是 getter 返回的地图。并在不将其分配给变量的情况下使用地图。因此,getter 返回的值可能已立即被破坏。
- 那么如果我的猜测是正确的呢?
- 为什么它返回地图的大小而不是它的结束迭代器?
#include <iostream>
#include <map>
class B {
long long id_;
public:
B() = default;
explicit B(long long);
~B() = default;
};
B::B(long long int id) : id_(id) {}
class A {
std::string id_;
std::map<long long, std::shared_ptr<B>> b_;
public:
A() = default;
explicit A(std::string id);
~A() = default;
const std::string &id() const;
std::map<long long, std::shared_ptr<B>> b();
};
A::A(std::string id): id_(id) {
b_[1] = std::make_shared<B>(1);
b_[2] = std::make_shared<B>(2);
}
const std::string &A::id() const {
return id_;
}
std::map<long long, std::shared_ptr<B>> A::b() {
return b_;
}
int main() {
std::shared_ptr<A> a = std::make_shared<A>("arst");
if (a->b().find(3) != a->b().end()) {
std::cout << a->b().find(3)->first << std::endl;
std::cout << a->b().at(3) << std::endl;
}
}
运行如下:
clang --version
Apple LLVM version 10.0.0 (clang-1000.10.44.4)
Target: x86_64-apple-darwin18.2.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
带输出:
clang++ test.cc -std=c++11
./a.out
2
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: map::at: key not found
[1] 64348 abort ./a.out
std::map<long long, std::shared_ptr<B>> A::b();
您按值返回map
,因此每次调用a->b()
时,您都会创建地图的新副本b_
这就是进行这种比较的原因:
a->b().find(3) != a->b().end()
。是未定义的行为,因为每次调用 b()
都会返回不同的映射,并且比较来自不同容器的迭代器是未定义的行为。
更改声明(和定义)以返回 ( const
-) 引用:
const std::map<long long, std::shared_ptr<B>>& A::b();
您的函数A::b()
按值返回映射。这意味着将返回一个副本,每次调用它时都是唯一的副本,并且其迭代器与任何其他副本的迭代器不兼容。
改为通过引用返回。
相关文章:
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 运行同一解决方案的另一个项目的项目
- 挂起和取消挂起一个文件DLL
- 用C++中的一个变量定义一个常量
- 函数向量_指针有不同的原型,我可以构建一个吗
- 在c++中用vector填充一个简单的动态数组
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 预处理器:插入结构名称中的前一个行号
- 我在c++代码中生成了一个运行时#3异常
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 从链接列表c++中删除一个项目
- 告诉一个 const char 数组,除了编译时 C 样式的字符串外,它不以 '