我有一个类似下面代码片段的用例,在 getter 返回的映射中使用 map::find
来查找不存在的键实际上会找到一个迭代器,其第一个值是 map (可能),因此不会像预期的那样运行,等于 map::end
这可能是因为我的 map 是 getter 返回的 map 。并在不将其分配给变量的情况下使用了 map 。这样 getter 返回值可能已经被立即销毁了。
- 那么如果我的猜测是正确的呢?
- 为什么它返回 map 的大小而不是它的结束迭代器?
#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()
都会创建 map 的新拷贝 b_
这就是为什么要进行这种比较:
a->b().find(3) != a->b().end()
...是未定义的行为,因为每次调用 b()
都会返回不同的映射和 comparing iterators from different container is undefined behavior .
更改您的声明(和定义)以返回一个 (const
-)reference:
const std::map<long long, std::shared_ptr<B>>& A::b();
关于c++ - 为什么将不存在的键应用于 map::find 会在 C++ 中返回具有第一个值映射大小的迭代器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54128830/