我将使用 MSVC,Visual Studio 2013。
假设我有一个结构体:
struct my_pair {
int foo, bar;
};
我希望能高效地添加一堆这些内容,而不需要创建一个临时变量再把它丢掉:
vector<my_pair> v;
v.push_back(41, 42); // does not work [a]
v.push_back({41,42}); // works [b]
v.emplace_back(41,42); // does not work [c]
v.emplace_back({41,42}); // does not work [d]
v.emplace_back(my_pair{41,42}); //works [e]
如果我在我的代码中添加构造函数和复制构造函数:
my_pair(int foo_, int bar_) : foo(foo_), bar(bar_)
{
cout << "in cstor" << endl;
}
my_pair(const my_pair& copy) : foo(copy.foo), bar(copy.bar)
{
cout << "in copy cstor" << endl;
}
然后行为发生了改变:
v.push_back(41, 42); // does not work [f]
v.push_back({41,42}); // displays "in cstor" and "in copy cstor" [g]
v.emplace_back(41,42); // displays "in cstor" [h]
v.emplace_back({41,42}); // does not work [i]
v.emplace_back(my_pair{41,42}); // "in cstor" and "in copy cstor" [j]
如果我添加了一个移动构造函数:
my_pair(my_pair&& move_) : foo(move_.foo), bar(move_.bar)
{
cout << "in move cstor" << endl;
}
那么:
v.emplace_back(my_pair{41,42}); //displays "in cstor", "in move cstor" [k]
v.emplace_back({41,42}); // still does not work [l]
v.push_back({41,42}); // displays "in cstor", "in move cstor" [m]
问题:对于[a,b],我理解为原因是有效和无效的。
对于[c],它不起作用是因为没有构造函数将参数转发到其中。
对于[d],为什么它不能像push case一样工作?
对于[e],为什么在添加类名时它可以工作?
对于[h],如果有一个将参数映射到成员的构造函数,它似乎是最有效的代码。
对于[j],这似乎与push_back一样糟糕,而且额外的打字让我不确定为什么任何人都应该在push_back上使用这个函数。
对于[k,m],增加了移动构造函数后,看起来正在调用
push_back(T&&)
,其结果与emplace相同。但是,再次出现额外的打字,我不确定为什么任何人都会这样做。
我读到MSVC不会自动添加移动构造函数:Why is copy constructor called in call to std::vector::emplace_back()?
[d,e]之间有什么区别,为什么emplace很挑剔。为什么 push_back(T&&)
可以工作而不需要添加结构体名称?
我只有在知道有一个构造函数以每个成员作为参数时才能充分利用emplace的好处吗?
我应该坚持使用 push_back
吗?有没有理由使用 emplace_back(structname {1,2,3})
而不是使用 push_back({1,2,3})
,因为它最终会调用 push_back(T&&)
,并且打字更容易?
第三,emplace_back(arg1,arg2,etc)
如何进行魔法以完全避免复制或移动构造函数?
emplace_back({42, 42}
通常不起作用,因为它变成了两个整数的initializer-list
,而不是一个my_pair
结构体。我认为如果你还添加了一个initializer list
构造函数,这个emplace_back调用可能会起作用。当然,人们可能会认为这会直接起作用,但你还必须考虑到emplace_back
的完美转发语义: 在大多数情况下,除非你明确命名类型,否则像emplace_back
这样的完美转发函数将以所给定的一切为准,没有额外的考虑或转换。 - user3010322