我有一个类似下面的代码片段的用例,在获取返回的映射中使用map::find
来查找不存在的键实际上会找到一个迭代器,其第一个值是映射的大小(可能),因此不会表现出预期的效果,等于map::end
这可能是因为我的地图是吸气剂返回的地图。并消耗了地图,而没有将其分配给变量。这样,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
答案 0 :(得分:11)
std::map<long long, std::shared_ptr<B>> A::b();
您将按值返回map
,因此每次调用a->b()
时,都会创建地图b_
的新副本,这就是这种比较的原因:
a->b().find(3) != a->b().end()
...是未定义的行为,因为每次调用b()
都会返回不同的映射和comparing iterators from different container is undefined behavior。
更改声明(和定义)以返回(const
-)引用:
const std::map<long long, std::shared_ptr<B>>& A::b();
答案 1 :(得分:9)
您的函数A::b()
通过值返回映射 。这意味着将返回一个 copy ,每次调用该 unique 副本,并且其迭代器与任何其他副本的迭代器不不兼容
通过引用返回 。