我正在通过Josuttis的“使用地图作为关联数组”(来自The C++ Standard Library - A Tutorial and Reference, 2nd Edition)并在Stack Overflow上遇到Using a std::map as an associative array。现在我对插入地图时调用的构造函数有了更多的疑问。
这是我的示例程序(不使用最佳编码方法;请原谅我):
class C
{
public:
string s;
C() { cout << "default " << endl;}
C(const string& p) : s(p)
{ cout << "one param" << endl;}
C(const C& obj)
{
if (this != &obj)
{
s = obj.s;
}
cout << "copy constr" << endl;
}
C& operator = (const C& obj)
{
if (this != &obj)
{
s = obj.s;
}
cout << "copy initializer" << endl;
return *this;
}
};
int main()
{
map<int,C> map1;
C obj("test");
cout << "Inserting using index" << endl;
map1[1] = obj;
cout << "Inserting using insert / pair" << endl;
map1.insert(make_pair(2,obj));
}
该程序的输出是:
one param
Inserting using index
default
copy constr
copy constr
copy initializer
Inserting using insert / pair
copy constr
copy constr
copy constr
copy constr
我假设按索引初始化地图应调用默认构造函数,然后调用赋值运算符。
但执行map1[1] = obj
会创建以下输出;
Inserting using index
default
copy constr
copy constr
copy initializer
有人可以帮助我更好地理解初始化吗?
答案 0 :(得分:8)
如果你读了std :: map的规范,那就说operator []相当于(在这种情况下)
(*((this->insert(make_pair(1,C()))).first)).second
所以这解释了你看到的所有构造函数调用。首先,它调用默认构造函数C()。然后它调用make_pair,它复制C对象。然后它调用insert,它生成你刚刚创建的pair对象的副本,再次调用C拷贝构造函数。最后,它调用赋值运算符将插入的对象设置为您指定的对象。
答案 1 :(得分:2)
#include <string>
#include <map>
#include <iostream>
using namespace std;
class C
{
public:
string s;
C()
{
cout << "default " << endl;
}
C(const string& p)
: s(p)
{
cout << "one param(" << s << ")" << endl;
}
C(const C& obj)
:s(obj.s)
{
cout << "copy constr(" << s << ")" <<endl;
}
C& operator = (const C& obj)
{
cout << "copy initializer\t" <<;
C copy(obj);
std::swap(s,copy.s);
return *this;
}
};
int main()
{
map<int,C> map1;
cout << "Inserting using index" << endl;
map1[1] = C("Plop");
}
看起来默认创建并复制了它 然后,外部的一旦被放置到位就会被激活。
Inserting using index
default
copy constr()
copy constr()
one param(Plop)
copy initializer copy constr(Plop)
答案 2 :(得分:0)
如果您只是执行map[1];
会怎样?这可能涉及内部副本,具体取决于标准库使用的map
的实现。
答案 3 :(得分:0)
实际上map1[1] = obj
将首先创建pair