I have a use case like the code snippet below, using map::find
in a getter returned map to find a non-exist key would actually find a iterator which first value is the size of the map (likely), thus would not behave as expect, equals with map::end
this is probably because of my map was a getter returned map. And consumed the map without assign it to a variable. So that the getter returned value may have been destructed immediately.
#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;
}
}
run as below:
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
with output:
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 operator[] inserts the default constructed value type in to the map if the key provided for the lookup doesn't exist. So you will get an empty string as the result of the lookup.
map find() function in C++ STL Return Value: The function returns an iterator or a constant iterator which refers to the position where the key is present in the map. If the key is not present in the map container, it returns an iterator or a constant iterator which refers to map. end().
To check if a value exists in a map:Convert the iterator to an array and call the includes() method on the array, passing it the specific value as a parameter. The includes method returns true if the value is contained in the array and false otherwise.
std::map<long long, std::shared_ptr<B>> A::b();
You are returning the map
by value, so each time you call a->b()
you create a new copy of the map b_
which is why this kind of comparison:
a->b().find(3) != a->b().end()
...is undefined behavior since each call to b()
returns a different map and comparing iterators from different container is undefined behavior.
Change your declaration (and definition) to return a (const
-)reference:
const std::map<long long, std::shared_ptr<B>>& A::b();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With