c++11 :emplace_back
在STL中,进行插入元素时,有insert和push两种选择方式,在“右值引用”和移动语义时,提出了更高效的插入方法:
函数原型:
template <class... Args>
void emplace_back (Args&&... args);
在容器尾部添加一个元素,这个元素原地构造,不需要触发拷贝构造和转移构造。而且调用形式更加简洁,直接根据参数初始化临时对象的成员。
源码push_back模板:
void push_back(value_type&& _Val)
{ // insert by moving into element at end
if (_Inside(_STD addressof(_Val))) //先 检查数组中是否有数据 有数据就插入end ,
{ // push back an element
size_type _Idx = _STD addressof(_Val) - _Unfancy(this->_Myfirst());
if (this->_Mylast() == this->_Myend())
_Reserve(1);
_Orphan_range(this->_Mylast(), this->_Mylast());
this->_Getal().construct(_Unfancy(this->_Mylast()),
_STD forward<value_type>(this->_Myfirst()[_Idx]));
++this->_Mylast();
}
else //没有数据
{ // push back a non-element
if (this->_Mylast() == this->_Myend())
_Reserve(1);
_Orphan_range(this->_Mylast(), this->_Mylast());
this->_Getal().construct(_Unfancy(this->_Mylast()),
_STD forward<value_type>(_Val));
++this->_Mylast();
}
}
push_back是先检查是否有数据,然后再插入数据。
emplace_back源码如下:
template<class... _Valty>
void emplace_back(_Valty&&... _Val) //直接插入end
{ // insert by moving into element at end
if (this->_Mylast() == this->_Myend())
_Reserve(1);
_Orphan_range(this->_Mylast(), this->_Mylast());
this->_Getal().construct(_Unfancy(this->_Mylast()),
_STD forward<_Valty>(_Val)...);
++this->_Mylast();
}
emplace_back 是直接插入end 的 而且默认调用构造函数和析构函数。
例程如下所示:
#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.\n";
}
President(const President& other)
: name(std::move(other.name)), country(std::move(other.country)), year(other.year)
{
std::cout << "I am being copy constructed.\n";
}
President(President&& other)
: name(std::move(other.name)), country(std::move(other.country)), year(other.year)
{
std::cout << "I am being moved.\n";
}
President& operator=(const President& other);
};
int main()
{
std::vector<President> elections;
std::cout << "emplace_back:\n";
elections.emplace_back("Nelson Mandela", "South Africa", 1994); //没有类的创建
std::vector<President> reElections;
std::cout << "\npush_back:\n";
reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936));
std::cout << "\nContents:\n";
for (President const& president: elections) {
std::cout << president.name << " was elected president of "
<< president.country << " in " << president.year << ".\n";
}
for (President const& president: reElections) {
std::cout << president.name << " was re-elected president of "
<< president.country << " in " << president.year << ".\n";
}
}
输出:
emplace_back:
I am being constructed.
push_back:
I am being constructed.
I am being moved.
Contents:
Nelson Mandela was elected president of South Africa in 1994.
Franklin Delano Roosevelt was re-elected president of the USA in 1936.
版权声明:本文为weixin_42258743原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。