C++11中,针对顺序容器(如vector 、deque 、list ),新标准引入了三个新成员函数:emplace_front 、emplace 和emplace_back ,这些操作构造而不是拷贝元素。这些操作分别对应push_front 、insert 和push_back ,允许我们将元素放置在容器头部、一个指定位置之前或容器尾部。
当调用push 或insert 成员函数时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中。而当我们调用一个emplace 成员函数时,则是将参数传递给元素类型的构造函数。emplace 成员使用这些参数在容器管理的内存空间中直接构造元素。
emplace 函数的参数根据元素类型而变化,参数必须与元素类型的构造函数相匹配。emplace 函数在容器中直接构造元素。传递给emplace 函数的参数必须与元素类型的构造函数相匹配。
其它容器中,std::forward_list 中的emplace_after 、emplace_front 函数,std::map /std::multimap 中的emplace 、emplace_hint 函数,std::set /std::multiset 中的emplace 、emplace_hint ,std::stack 中的emplace 函数,等emplace 相似函数操作也均是构造而不是拷贝元素。
emplace 相关函数可以减少内存拷贝和移动。当插入rvalue ,它节约了一次move 构造,当插入lvalue ,它节约了一次copy 构造。
配合下面的测试代码理解:
#include <vector>
#include <string>
#include <iostream>
struct President
{
std::string name;
std::string country;
int year;
President(std::string && p_name, std::string && p_country, int p_year)
: name(std::move(p_name)), country(std::move(p_country)), year(p_year)
{
std::cout << "I am being constructed.";
}
President(President&& other)
: name(std::move(other.name)), country(std::move(other.country)), year(other.year)
{
std::cout << "I am being moved.";
}
President& operator=(const President& other) = default;
};
int main()
{
std::vector<President> elections;
std::cout << "emplace_back:";
elections.emplace_back("Nelson Mandela", "South Africa", 1994);
std::vector<President> reElections;
std::cout << "push_back:";
reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936));
std::cout << "Contents:";
for (President const& president : elections) {
std::cout << president.name << " was elected president of "
<< president.country << " in " << president.year << ".";
}
for (President const& president : reElections) {
std::cout << president.name << " was re-elected president of "
<< president.country << " in " << president.year << ".";
}
}
代码输出为:
emplace_back:
I am being constructed.
push_back:
I am being constructed.
I am being moved.
|