ron*_*nag 684 c++ stl visual-studio-2010 move-semantics c++11
我有点困惑有关之间的差异push_back
和emplace_back
.
void emplace_back(Type&& _Val);
void push_back(const Type& _Val);
void push_back(Type&& _Val);
Run Code Online (Sandbox Code Playgroud)
因为有一个push_back
超载采用右值参考我不太明白目的是emplace_back
什么?
Tho*_*tit 519
除了访客所说的:
void emplace_back(Type&& _Val)
MSCV10提供的功能是不符合和冗余的,因为正如您所指出的那样,它完全等同于push_back(Type&& _Val)
.
但真正的C++ 0x形式emplace_back
是真正有用的:void emplace_back(Args&&...)
;
而不是采用value_type
它需要一个可变参数列表,这意味着你现在可以完美地转发参数并直接将一个对象构造成一个容器,而不是一个临时的.
这很有用,因为无论RVO和移动语义多么聪明,还有一些复杂的情况,其中push_back可能会产生不必要的副本(或移动).例如,使用a的传统insert()
功能std::map
,您必须创建一个临时的,然后将其复制到一个std::pair<Key, Value>
,然后将其复制到地图中:
std::map<int, Complicated> m;
int anInt = 4;
double aDouble = 5.0;
std::string aString = "C++";
// cross your finger so that the optimizer is really good
m.insert(std::make_pair(4, Complicated(anInt, aDouble, aString)));
// should be easier for the optimizer
m.emplace(4, anInt, aDouble, aString);
Run Code Online (Sandbox Code Playgroud)
那么为什么他们没有在MSVC中实现正确版本的emplace_back呢?实际上,它在一段时间之前也让我感到烦恼,所以我在Visual C++博客上问了同样的问题.以下是来自Microsoft的Visual C++标准库实现的官方维护者Stephan T Lavavej的答案.
问:beta 2 emplace现在只是某种占位符吗?
答:您可能知道,VC10中没有实现可变参数模板.我们使用预处理器机器来模拟它们,例如
make_shared<T>()
,元组和新事物<functional>
.这种预处理器机器相对难以使用和维护.此外,它显着影响编译速度,因为我们必须重复包含子标题.由于我们的时间约束和编译速度问题的组合,我们没有在我们的emplace函数中模拟可变参数模板.当在编译器中实现可变参数模板时,您可以期望我们将在库中利用它们,包括在我们的emplace函数中.我们非常重视一致性,但不幸的是,我们不能一次完成所有事情.
这是一个可以理解的决定.每个尝试过一次用预处理器可怕的技巧模仿可变参数模板的人都知道这些东西有多恶心.
vis*_*tor 187
emplace_back
不应该采用类型的参数vector::value_type
,而是转发到附加项的构造函数的可变参数.
template <class... Args> void emplace_back(Args&&... args);
Run Code Online (Sandbox Code Playgroud)
可以传递value_type
将被转发到复制构造函数的文件.
因为它转发参数,这意味着如果你没有rvalue,这仍然意味着容器将存储"复制"副本,而不是移动副本.
std::vector<std::string> vec;
vec.emplace_back(std::string("Hello")); // moves
std::string s;
vec.emplace_back(s); //copies
Run Code Online (Sandbox Code Playgroud)
但是上面的内容应该与之相同push_back
.它可能更适用于以下用例:
std::vector<std::pair<std::string, std::string> > vec;
vec.emplace_back(std::string("Hello"), std::string("world"));
// should end up invoking this constructor:
//template<class U, class V> pair(U&& x, V&& y);
//without making any copies of the strings
Run Code Online (Sandbox Code Playgroud)
vad*_*bot 73
优化emplace_back
可以在下一个例子中证明.
对于emplace_back
构造函数A (int x_arg)
将被调用.并且
push_back
A (int x_arg)
首先move A (A &&rhs)
被称为并且之后被称为.
当然,构造函数必须标记为explicit
,但是对于当前示例来说,删除显式性是很好的.
#include <iostream>
#include <vector>
class A
{
public:
A (int x_arg) : x (x_arg) { std::cout << "A (x_arg)\n"; }
A () { x = 0; std::cout << "A ()\n"; }
A (const A &rhs) noexcept { x = rhs.x; std::cout << "A (A &)\n"; }
A (A &&rhs) noexcept { x = rhs.x; std::cout << "A (A &&)\n"; }
private:
int x;
};
int main ()
{
{
std::vector<A> a;
std::cout << "call emplace_back:\n";
a.emplace_back (0);
}
{
std::vector<A> a;
std::cout << "call push_back:\n";
a.push_back (1);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
call emplace_back:
A (x_arg)
call push_back:
A (x_arg)
A (A &&)
Run Code Online (Sandbox Code Playgroud)
这里显示了push_back和emplace_back的漂亮代码。
http://en.cppreference.com/w/cpp/container/vector/emplace_back
您可以在push_back而非emplace_back上看到移动操作。
emplace_back
符合实现将vector<Object>::value_type
在添加到向量时将参数转发给构造函数.我记得Visual Studio不支持可变参数模板,但在Visual Studio 2013 RC中将支持可变参数模板,因此我想将添加一致的签名.
有了emplace_back
,如果你将参数直接转发给vector<Object>::value_type
构造emplace_back
函数,严格来说,你不需要一个类型可以移动或复制功能.在这种vector<NonCopyableNonMovableObject>
情况下,这没有用,因为vector<Object>::value_type
需要可复制或可移动类型来增长.
但请注意,这可能很有用std::map<Key, NonCopyableNonMovableObject>
,因为一旦在地图中分配了一个条目,它就不再需要被移动或复制了vector
,这意味着你可以std::map
有效地使用既不可复制也不能复制的映射类型.活动.
小智 7
如果是列表,还需要一个:
// constructs the elements in place.
emplace_back("element");
//It will create new object and then copy(or move) its value of arguments.
push_back(explicitDataType{"element"});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
292892 次 |
最近记录: |