- 如果是直接插入对象
push_back()
和emplace_back()
没有区别 - 但如果直接传入构造函数所需参数,
emplace_back()
会直接在容器底层构造对象,省去了调用拷贝构造或者移动构造的过程
class Test
{
public:Test(int a){cout<<"Test(int)"<<endl;}Test(int a,int b){cout<<"Test(int,int)"<<endl;}Test(const Test&){cout<<"Test(const Test&)"<<endl;}~Test(){cout<<"~Test()"<<endl;}Test(Test&&){cout<<"Test(Test&&)"<<endl;}
};
int main()
{Test t1(10);//Test(int)vector<Test> v;v.reserve(100);cout<<"========1=========="<<endl;//直接插入对象,两个没有区别 v.push_back(t1);//Test(const Test&) v.emplace_back(t1);//Test(const Test&)cout<<"=========2========="<<endl;//直接插入对象,两个没有区别 v.push_back(Test(20));//Test(int) Test(Test&&) ~Test()v.emplace_back(Test(20));//Test(int) Test(Test&&) ~Test()cout<<"=========3========="<<endl;//给emplace传入Test对象构造所需的参数,直接在容器底层构造对象即可 v.emplace_back(20);//Test(int)v.emplace_back(30,40);//Test(int,int)cout<<"=========4========="<<endl;/*map<int,string> mp;m.insert(make_pair(10,"zhangsan"));//构造临时对象 调用右值引用拷贝构造 析构临时对象m.emplace(10,"zhangsan") ;//在map底层直接调用普通构造函数,生成一个pair对象即可 */return 0;
}
底层实现:
//空间配置器
template<typename T>
struct Allocator
{T* allocate(size_t size)//负责内存开辟 {return (T*)malloc(sizeof(T)*size);}template<typename... Types>void construct(T *ptr,Types&&... args)//负责构造 {new (ptr) T(std::forward<Types>(args)...);//定位new 在指定的内存上 构造一个值为val的对象,会调用 T类型的拷贝构造 }
};template<typename T,typename Alloc = Allocator<T>>
class vector
{
public:vector():vec_(nullptr),size_(0),idx_(0){}void reserve(size_t size){vec_ = allocator.allocate(size);size_ = size; }template<typename Type>void push_back(Type&& val){allocator.construct(vec_+idx_,std::forward<Type>(val));idx_++;}template<typename... Types>void emplace_back(Types&&... args){allocator.construct(vec_+idx_,std::forward<Types>(args)...);idx_++;}
private:T* vec_;int size_;//内存大小 int idx_;Alloc allocator;//空间配置器
};