C++ c++;11使用struct放置和推回语法

C++ c++;11使用struct放置和推回语法,c++,c++11,rvalue-reference,C++,C++11,Rvalue Reference,我正在使用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.emp

我正在使用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(my_pair&& move_) : foo(move_.foo), bar(move_.bar)
{
    cout << "in move cstor" << endl;
}
问题:
对于[a,b]我理解工作和不工作的原因。
对于[c],它不起作用,因为没有可转发参数的构造函数
对于[d],为什么它不像push情况下那样工作
对于[e],为什么在添加类名时它会起作用
对于[h],如果有一个将参数映射到成员的构造函数,那么这似乎是最有效的代码
对于[j],这似乎和推回一样糟糕,加上额外的打字,我不知道为什么有人要在推回上这样做
对于[k,m],随着移动构造函数的添加,似乎调用了
push_back(T&&)
,从而产生与emplace相同的性能。但再一次,由于额外的打字,我不知道为什么会有人这样做

我了解到MSVC没有为您添加移动构造函数:

[d,e]之间的区别是什么?为什么emplace会对此挑三拣四。为什么
push_-back(T&&)
在不添加结构名称的情况下工作

如果我知道有一个构造函数将每个成员作为参数,那么我只能得到emplace的全部好处

我是否应该继续使用
向后推
?是否有任何理由使用
emplace\u back(structname{1,2,3})
而不是
push\u back({1,2,3})
,因为它最终会调用
push\u back(T&)
,并且更容易键入

第三,
emplace\u back(arg1、arg2等)
如何发挥其魔力,完全避免复制或移动构造函数?

对于
v.emplace\u back({41,42}),请参阅


v.emplace_-back(41,42)不起作用,因为标准中有一些规则(有些强调):

表101-可选序列容器操作

表达式:
a.emplace\u back(args)

返回类型:
void

操作语义:
追加一个类型为
T
的对象,该对象由
std::forward构造,如果可能的话,
a.construct(p,std::forward,它调用
::new((void*)p)U(std::forward.
push_back()
的参数不会被推导出来,这意味着通过执行
push_back({1,2})
,首先创建一个具有向量元素类型的临时对象,并用
{1,2}
初始化。然后,该临时对象将被传递到
push_back(T&&)


我应该坚持使用push_back吗?有没有理由使用emplace_back(structname{1,2,3})而不是push_back({1,2,3}),因为它最终会调用push_back(T&&),并且更容易键入


基本上,
emplace*
函数旨在优化和消除创建临时对象以及在插入对象时复制或移动构造对象的成本。但是,对于聚合数据类型,执行类似
emplace\u back(1、2、3)的操作
是不可能的,插入它们的唯一方法是创建一个临时文件,然后进行复制或移动,然后尽一切可能使用更简洁的语法,然后使用
push_back({1,2,3})
,它的性能基本上与
emplace_back(structname{1,2,3})相同

作为一个快速评论,
emplace\u back({42,42}一般不起作用,因为它变成了两个整数的<代码>初始化列表< /代码>,而不是<代码> MyOxBuff[/Calp> Stutt。我认为,如果添加了<代码>初始化器列表构造函数,EMPANTHORE调用可能会起作用。当然,人们会认为这会直接解决,但您也必须考虑到完美。
emplace\u-back
的转发语义:在大多数情况下,除非您明确指定类型,否则像
emplace\u-back
这样完美的转发功能将完全按照面值接收任何给定的内容,而无需额外考虑或转换。我不同意您的“不复制就无法插入聚合”答案最后一段中的陈述。您可以始终执行以下操作:v.emplace_back();v.back().foo=41;v.back().bar=42;@PowerGamer,也就是说,如果聚合是默认可构造的。但是,是的,这是一个很好的添加点。(我直到现在才真正意识到您指出了这一点,谢谢)
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]