Copy constructor 在调用 std::unordered_map 的 insert 时会被调用吗?

huangapple go评论99阅读模式
英文:

Will copy constructor be called when calling insert of std::unordered_map

问题

以下是您要翻译的内容:

"I have a std::unordered_map and I found that the object I insert into it is different from that I got from it by using for range traversing.

I doubt that there might be some object copying happening here but after I added some dumping to the copy constructor, it is not called at all.

Could any one tell me what is happening in the background when inserting and traversing a std::unordered_map.

I tried the following code and it dumped:

[Result]

  1. mypair constuctor
  2. mypair constuctor
  3. string1 address:0x7ffccb813ba0
  4. string2 address:0x7ffccb813bd0
  5. ++++++++++++++++
  6. auto &x address:0x55fb40529378
  7. string2: 0.5
  8. auto &x address:0x55fb405292c8
  9. string1: 0.3
  10. ++++++++++++++++
  11. auto x address:0x7ffccb813c00
  12. string2: 0.5
  13. auto x address:0x7ffccb813c00
  14. string1: 0.3
  15. ++++++++++++++++

[Source]

  1. #include <iostream>
  2. #include <string>
  3. #include <unordered_map>
  4. class mypair : public std::pair<std::string,double> {
  5. public:
  6. mypair(std::string str, double num):std::pair<std::string,double>(str, num) {
  7. std::cout<<"mypair constuctor"<<std::endl;
  8. }
  9. mypair( const mypair& ) {
  10. std::cout<<"mypair copy constuctor"<<std::endl;
  11. }
  12. mypair& operator=(const mypair&) {
  13. std::cout<<"mypair copy assignment"<<std::endl;
  14. return *this;
  15. }
  16. };
  17. int main ()
  18. {
  19. std::unordered_map<std::string,double> myMap;
  20. mypair string1 ("string1", 0.3);
  21. mypair string2 ("string2", 0.5);
  22. std::cout << "string1 address:" << &string1 << std::endl;
  23. std::cout << "string2 address:" << &string2 << std::endl;
  24. std::cout <<"++++++++++++++++"<< std::endl;
  25. myMap.insert (string1);
  26. myMap.insert (string2);
  27. for (auto& x: myMap) {
  28. std::cout << "auto &x address:"<< &x << std::endl<< x.first << ": " << x.second << std::endl;
  29. }
  30. std::cout <<"++++++++++++++++"<< std::endl;
  31. for (auto x: myMap) {
  32. std::cout << "auto x address:"<< &x << std::endl<< x.first << ": " << x.second << std::endl;
  33. }
  34. std::cout <<"++++++++++++++++"<< std::endl;
  35. return 0;
  36. }
英文:

I have a std::unordered_map and I found that the object I insert into it is different from that I got from it by using for range traversing.

I doubt that there might be some object copying happening here but after I added some dumping to the copy constructor, it is not called at all.

Could any one tell me what is happening in the background when inserting and traversing a std::unordered_map.

I tried the following code and it dumped:

[Result]

  1. mypair constuctor
  2. mypair constuctor
  3. string1 address:0x7ffccb813ba0
  4. string2 address:0x7ffccb813bd0
  5. ++++++++++++++++
  6. auto &x address:0x55fb40529378
  7. string2: 0.5
  8. auto &x address:0x55fb405292c8
  9. string1: 0.3
  10. ++++++++++++++++
  11. auto x address:0x7ffccb813c00
  12. string2: 0.5
  13. auto x address:0x7ffccb813c00
  14. string1: 0.3
  15. ++++++++++++++++

[Source]

  1. #include <iostream>
  2. #include <string>
  3. #include <unordered_map>
  4. class mypair : public std::pair<std::string,double> {
  5. public:
  6. mypair(std::string str, double num):std::pair<std::string,double>(str, num) {
  7. std::cout<<"mypair constuctor"<<std::endl;
  8. }
  9. mypair( const mypair& ) {
  10. std::cout<<"mypair copy constuctor"<<std::endl;
  11. }
  12. mypair& operator=(const mypair&) {
  13. std::cout<<"mypair copy assignment"<<std::endl;
  14. return *this;
  15. }
  16. };
  17. int main ()
  18. {
  19. std::unordered_map<std::string,double> myMap;
  20. mypair string1 ("string1", 0.3);
  21. mypair string2 ("string2", 0.5);
  22. std::cout << "string1 address:" << &string1 << std::endl;
  23. std::cout << "string2 address:" << &string2 << std::endl;
  24. std::cout <<"++++++++++++++++"<< std::endl;
  25. myMap.insert (string1);
  26. myMap.insert (string2);
  27. for (auto& x: myMap) {
  28. std::cout << "auto &x address:"<< &x << std::endl<< x.first << ": " << x.second << std::endl;
  29. }
  30. std::cout <<"++++++++++++++++"<< std::endl;
  31. for (auto x: myMap) {
  32. std::cout << "auto x address:"<< &x << std::endl<< x.first << ": " << x.second << std::endl;
  33. }
  34. std::cout <<"++++++++++++++++"<< std::endl;
  35. return 0;
  36. }

答案1

得分: 5

以下是翻译好的内容:

你没有看到对mypair的复制构造函数的任何调用,因为std::unordered_map内部不使用该对类型。

  1. using value_type = std::pair<const Key, Value>;

...实际上是内部使用的对类型。你的mypair可以隐式转换为value_type,因此应该调用以下成员函数:

  1. template<class P>
  2. std::pair<iterator, bool> insert(P&& value);

这既不复制也不复制分配mypair,它将从传递的对的内容构造一个std::pair

如果你想尽量减少复制和开销,你应该使用emplacetry_emplace

英文:

You're not seeing any calls to the copy constructor of mypair, because that is not the pair type that the std::unordered_map uses internally.

  1. using value_type = std::pair&lt;const Key, Value&gt;;

... is the pair type that is actually used inside. Your mypair is implicitly convertible to the value_type, so the following member function should be called:

  1. template&lt; class P &gt;
  2. std::pair&lt;iterator, bool&gt; insert( P&amp;&amp; value );

This neither copies nor copy-assigns a mypair, it will construct a std::pair from the contents of the pair you pass.

If you want to minimize copying and overhead as much as possible, you should instead use emplace or try_emplace.

huangapple
  • 本文由 发表于 2023年7月6日 16:38:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76626987.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定