c++中emplace_back()与push_back()的区别,STL,vector,list,map
emplace_back() 和 push_back() 的区别,就在于底层实现的机制不同。push_back() 向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素)。使用到了拷贝构造函数。而 emplace_back() 在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程。直接使用构造参数列表来添加
emplace_back() 和 push_back() 的区别,就在于底层实现的机制不同。
push_back() 向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素)。使用到了拷贝构造函数。
而 emplace_back() 在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程。直接使用构造参数列表来添加元素的方法,它会使用到了移动构造函数 move(不用拷贝一个复制品)。
源码实现的区别:
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
std::forward<_Args>(__args)...); // emplace_back()
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
__x); // push_back()
std::forward()
函数而言,本质上是一个类型转换函数
新版本的原型展示:
void push_back(const value_type& x);
void push_back(value_type&& x);
<typename... Args> reference emplace_back(Args&&... args);
两者区别:
push_back:传入一个事先存在的元素对象,调用的是拷贝或移动构造来生成这个新压入的元素对象:construct(*des, class_name&|&& x)
emplace_back:多个事先存在的对象,调用示义:construct(*des, other_type &x|&&x, type_name &|&&,...)
可以看见,emplace_back传参不定,编译器需要在调用时才生成具体的实现,push_back只是emplace_back的两个偏移化版本。
push_back只能用类中的拷贝或移动构造,而emplace_back还可以是类中的其他多参数的构造函数(自定义的类,调用的构造函数也由自己定义,没有定义或没有就会报错),这是优点也是缺点(代码翻倍)
&&在普通函数中作为参数时,是万能引用,并不是右值引用,在函数体中会使用forward完美转发,调用时是复制或移动,和你传的值有关,你传左值它就用左值版本,传右值就用右值版本。
如果一个类没有上诉的拷贝或移动构造,则不能用于STL容器中,如果没有相应参数类型的构造实现,emplace_back编译不过,找不到它需要的对应构造函数。
move和copy构造唯一区别:move时,指针属性只是简单的拷贝指针,而copy中,指针属性被拷贝的同时,它所指的具体内容也还需要深度copy下去。
在实现类的两个构造时特别要注意这一点,move中要将旧对象的内部指针属性置nullptr,这意味着相应的对象不再适合使用了(这就是对象必须是临时对象的原因!转移后,内部的指针属性失效!)
move和copy的性能对比:正如上说,move只是指针优化,如果类本身没有指针属性,则它不需要move,我们也不必强制move不可,copy和move在内置类型和简单类型(指无指针属性、即构造时不需要new)没区别
更多推荐
所有评论(0)