push_back和emplace_back区别
在使用vector容器时,往容器里添加元素时,有push_back和emplace_back两种方法,一般用得最多得是push_back,下面看看这两种方法得区别:
push_back源码,有重载得左值和右值,关于左值和右值可以查看
void push_back(value_type&& _Val) { // insert by moving into element at end if (_Inside(_STD addressof(_Val))) { // 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(); } } void push_back(const value_type& _Val) { // insert element at end if (_Inside(_STD addressof(_Val))) { // 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()), 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()), _Val); ++this->_Mylast(); } }
emplace_back源码:
template<class... _Valty> void emplace_back(_Valty&&... _Val) { // 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(); }
从源代码中可以看出,两者只有参数得区别,push_back参数为左值引用和右值引用,而emplace_back是一个参数包_Valty&&…,你可以向这个参数包传构造对象得参数即可。
实例分析:
class A { public: int i; A(int t) :i(t) { cout << "A()" << endl; } A(const A&a) :i(a.i) { cout << "拷贝构造" << endl; } A( A&&a) :i(a.i) { cout << "移动构造" << endl; } }; int main() { A a(1); vector<A> v1; v1.push_back(a); cout << "---------------" << endl; vector<A> v11; v11.push_back(A(2)); cout << "---------------" << endl; vector<A> v2; v2.emplace_back(A(3)); cout << "---------------" << endl; vector<A> v22; A aa(1); v22.emplace_back(aa); cout << "---------------" << endl; vector<A> v3; v3.emplace_back(11); return 0; }
从结果中可以看出,如果直接传对象给push_back和emplace_back,无论是实名对象还是匿名对象,结果都是一样的,但是emplance_back不同的是你可以直接传构造对象的参数,然后emplace_back函数里通过参数来直接构造对象,从而少了一次构造,效率更高。
下一篇:
java中引用类型和基本类型的区别