Let's say I have an unordered_map:
std::unordered_map<Key, BigObject> big_objects;
where BigObject
is like:
struct BigObject {
BigObject(P1, P2, P3); // <--- expensive
/*...*/
};
and I have a Key
k
, and a set of arguments for BigObject
s constructor P1
p1
, P2
p2
and P3
p3
.
If big_objects
already contains k
I want to do nothing. If big_objects
does not contain K
I want to construct and insert BigObject(p1,p2,p3)
Is it possible to do this with a single lookup on big_objects
?
ie Will emplace
or try_emplace
construct BigObject
if the key is already present?
Update
After some testing it seems like emplace
does construct BigObject
but try_emplace
doesn't?
ie
big_objects[k] = BigObject(p1,p2,p3) // insert k, k now present...
big_objects.emplace(k, p1, p2, p3); // does construct a BigObject
big_objects.try_emplace(k, p1, p2, p3); // does not construct a BigObject
Is this correct?
Yes, it is correct, this is the reason why try_emplace
exists, it doesn't touch its arguments if the key is already present.
Unlike insert or emplace, these functions do not move from rvalue arguments if the insertion does not happen, which makes it easy to manipulate maps whose values are move-only types, such as std::map<std::string, std::unique_ptr>. In addition, try_emplace treats the key and the arguments to the mapped_type separately, unlike emplace, which requires the arguments to construct a value_type (that is, a std::pair)
As a bonus point, you do not have to use the ugly std::piecewise_construct
tag to pass both the key and the value constructor arguments ( unless you want to inplace construct the key too).
Yes, like this algorithm problem: enter image description here
One solution is:
int findShortestSubArray(vector<int>& nums)
{
std::unordered_map<int, std::tuple<int, int, int>> map;
int s = nums.size();
for(int i = 0; i < s; ++i)
{
if(!map.try_emplace(nums.at(i), std::tuple<int, int, int>{1,i,i}).second)
{
++std::get<0>(map.at(nums.at(i)));
std::get<2>(map.at(nums.at(i))) = i;
}
}
//...
}
This solution takes the result of its execution from the return value of try_emplace()
and uses it as a condition for an if statement, end up with a very nice space-time overhead:
Execution Time: 32ms, beating 97.50% of users in all C++ commits
Memory consumption: 24.3MB, beating 93.47% of users in all C++ commits
but if I replace try_emplace()
with emplace()
, Space-time costs will balloon:
Execution Time: 84ms, beating 61.24% of users in all C++ commits
Memory consumption: 33.8MB, beating 6.65% of users in all C++ commits
This reason has been answered by other friends, and I think that's a good example of the difference between the two.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.