【发布时间】:2014-12-30 02:42:11
【问题描述】:
我试图更好地理解 std::unordered_map::emplace,并且我想我理解如果存在复制和移动构造函数,它们是如何被使用的。我在下面概述了每种不同用法的相关描述。如果有人发现描述有任何问题,请告诉我。
然而,我最好奇的是,当只定义默认和用户定义的构造函数时会发生什么?貌似根本没有调用默认构造函数,而自定义构造函数只调用了ONCE,那么unordered_map中新构造元素的FooBar成员是怎么填充的呢? (我想默认/用户定义的构造函数至少被调用两次)。另外,如果 FooBar 没有定义复制和移动构造函数,那么下面 3 种情况是否有任何行为差异?
注意:我知道这是一个微不足道的例子,深拷贝不是问题,所以复制/移动语义并没有真正产生任何显着的收益。我只是使用这个简化的例子来表达我的观点。
struct FooBar
{
FooBar()
{
printf("Foobar default constructor called\n");
};
FooBar(int* pFoo, int* pBar)
{
m_pFoo = pFoo;
m_pBar = pBar;
printf("Foobar user-defined constructor called\n");
};
FooBar(FooBar & rhs)
{
m_pBar = rhs.m_pBar;
m_pFoo = rhs.m_pFoo;
printf("Foobar copy constructor called\n");
};
FooBar(FooBar && rhs)
{
m_pBar = rhs.m_pBar;
m_pFoo = rhs.m_pFoo;
rhs.m_pBar = nullptr;
rhs.m_pFoo = nullptr;
printf("Foobar move constructor called\n");
};
int* m_pFoo;
int* m_pBar;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::unordered_map<int, FooBar> map;
//template< class... Args >
//std::pair<iterator, bool> emplace(Args&&... args);
// 1.
// Description: A lvalue of foobar1 is temporarily created, initialized, copied (via copy constructor)
// to supply the in-place constructed element's FooBar member, and destroyed
// Output (if both copy and move constructor exist): Foobar user-defined constructor called, Foobar copy constructor called
// Output (if both copy and move constructor don't exist): Foobar user-defined constructor called
{
FooBar foobar1 = {(int*)0xDEADBEEF, (int*)0x01010101};
map.emplace(10, foobar1);
}
// 2.
// Description: A rvalue of bar1 is temporarily created, initialized, moved (via move constructor)
// to supply the in-place constructed element's FooBar member, and destroyed
// Output (if both copy and move constructor exist): Foobar user-defined constructor called, Foobar move constructor called
// Output (if both copy and move constructor don't exist): Foobar user-defined constructor called
map.emplace(20, FooBar{(int*)0xDEADBEEF,(int*)0x01010101});
// 3.
// Description: A lvalue of foobar1 is temporarily created and initialized. It is then
// explicitly converted to a rvalue (via std::move), moved (via move constructor) to supply
// the in-place constructed element's FooBar member, and destroyed
// Output (if both copy and move constructor exist): Foobar user-defined constructor called, Foobar move constructor called
// Output (if both copy and move constructor don't exist): Foobar user-defined constructor called
{
FooBar foobar2 = {(int*)0xDEADBEEF, (int*)0x01010101};
map.emplace(30, std::move(foobar2));
}
return 0;
}
谢谢。
【问题讨论】:
-
FooBar(int* pFoo, int* pBar)不是“默认”构造函数。 -
您是否建议在创建地图中新构造的元素时调用默认构造函数而不是
FooBar(int* pFoo, int* pBar)?如果是这样,我如何覆盖该构造函数以查看消息?我只尝试了FooBar(),但也没有被调用。 -
不,我只是建议您的问题写得不准确,因为您所谓的“默认构造函数”不是。
-
好的,我会更新术语以使其更准确。
标签: c++ visual-c++ c++11 unordered-map