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 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>