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

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

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]

mypair constuctor
mypair constuctor
string1 address:0x7ffccb813ba0
string2 address:0x7ffccb813bd0
++++++++++++++++
auto &x address:0x55fb40529378
string2: 0.5
auto &x address:0x55fb405292c8
string1: 0.3
++++++++++++++++
auto x address:0x7ffccb813c00
string2: 0.5
auto x address:0x7ffccb813c00
string1: 0.3
++++++++++++++++

[Source]

#include <iostream>
#include <string>
#include <unordered_map>

class mypair : public std::pair<std::string,double> {
public:
      mypair(std::string str, double num):std::pair<std::string,double>(str, num) {
          std::cout<<"mypair constuctor"<<std::endl;
      }
      mypair( const mypair& ) {
          std::cout<<"mypair copy constuctor"<<std::endl;
      }
      mypair& operator=(const mypair&) {
          std::cout<<"mypair copy assignment"<<std::endl;
          return *this;
      }
};

int main ()
{
    std::unordered_map<std::string,double> myMap;
    mypair string1 ("string1", 0.3);
    mypair string2 ("string2", 0.5);
    std::cout << "string1 address:" << &string1 << std::endl;
    std::cout << "string2 address:" << &string2 << std::endl;
    std::cout <<"++++++++++++++++"<< std::endl;
    myMap.insert (string1);
    myMap.insert (string2);
    
    for (auto& x: myMap) {
        std::cout << "auto &x address:"<< &x << std::endl<< x.first << ": " << x.second << std::endl;
    }
    std::cout <<"++++++++++++++++"<< std::endl;
    
    for (auto x: myMap) {
        std::cout << "auto x address:"<< &x << std::endl<< x.first << ": " << x.second << std::endl;
    }
    std::cout <<"++++++++++++++++"<< std::endl;
    return 0;
}
英文:

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]

mypair constuctor
mypair constuctor
string1 address:0x7ffccb813ba0
string2 address:0x7ffccb813bd0
++++++++++++++++
auto &x address:0x55fb40529378
string2: 0.5
auto &x address:0x55fb405292c8
string1: 0.3
++++++++++++++++
auto x address:0x7ffccb813c00
string2: 0.5
auto x address:0x7ffccb813c00
string1: 0.3
++++++++++++++++

[Source]

#include <iostream>
#include <string>
#include <unordered_map>

class mypair : public std::pair<std::string,double> {
public:
      mypair(std::string str, double num):std::pair<std::string,double>(str, num) {
          std::cout<<"mypair constuctor"<<std::endl;
      }
      mypair( const mypair& ) {
          std::cout<<"mypair copy constuctor"<<std::endl;
      }
      mypair& operator=(const mypair&) {
          std::cout<<"mypair copy assignment"<<std::endl;
          return *this;
      }
};

int main ()
{
    std::unordered_map<std::string,double> myMap;
    mypair string1 ("string1", 0.3);
    mypair string2 ("string2", 0.5);
    std::cout << "string1 address:" << &string1 << std::endl;
    std::cout << "string2 address:" << &string2 << std::endl;
    std::cout <<"++++++++++++++++"<< std::endl;
    myMap.insert (string1);
    myMap.insert (string2);
    
    for (auto& x: myMap) {
        std::cout << "auto &x address:"<< &x << std::endl<< x.first << ": " << x.second << std::endl;
    }
    std::cout <<"++++++++++++++++"<< std::endl;
    
    for (auto x: myMap) {
        std::cout << "auto x address:"<< &x << std::endl<< x.first << ": " << x.second << std::endl;
    }
    std::cout <<"++++++++++++++++"<< std::endl;
    return 0;
}

答案1

得分: 5

以下是翻译好的内容:

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

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

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

template<class P>
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.

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:

template&lt; class P &gt;
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:

确定