c++ push_back()和emplace_back()区别


c++ push_back()和emplace_back()区别

一、区别:

都可以直接根据传入的参数选择匹配的构造函数隐式构造对象。
但隐式构造时:

1. push_back()

  • 如果未定义移动构造函数,传入到push_back()的参数与元素对应类的某个构造函数匹配,那么会隐式构造一个元素,首先调用构造函数构造临时对象,然后调用拷贝构造函数讲这个临时对象放入容器中。

  • 如果定义了移动构造函数,上述过程就会变成依次调用构造函数移动构造函数

2. emplace_back()

  • 在容器尾部添加一个元素, 传入到emplace_back()的参数与元素对应类的某个构造函数匹配, 这个元素原地构造对象,仅需要调用构造函数, 而不会调用拷贝构造函数或移动构造函数

3. 程序示例

#include 
#include 
using namespace std;
class Foo{
private:
    int a;
public:
    Foo(int num): a(num) {
        cout<<"Foo Constructor "< vec1;
    vec1.push_back(1);

    cout< vec2;
    vec2.emplace_back(2);
    vec2.emplace_back(3);
}

输出:

push_back:

Foo Constructor 1
move constructor  //若注释掉移动构造函数,此处将调用拷贝构造函数
Foo Destructor...

emplace_back:

Foo Constructor 2
Foo Constructor 3
copy constructor  //vec2扩容后,拷贝元素到新空间
Foo Destructor...  //vec2扩容后,旧空间中的元素析构
Foo Destructor...  //vec1中的元素析构
Foo Destructor...  //vec2中的元素析构
Foo Destructor...  //vec2中的元素析构

4. 疑问:为什么emplace_back:后,打印了一次拷贝构造函数,以及四次析构函数?

https://blog.csdn.net/luomoshusheng/article/details/48226517

因为定义的vector初始容量为0,加入一个元素容量扩容为1,再加入一个元素,分配新空间扩容为2,vector中元素要拷贝到新空间,旧元素销毁。

二、相同之处

  1. 拷贝构造函数和移动构造函数均已定义,push_back/emplace_back向容器中加入左值元素,均将调用构造函数和拷贝构造函数拷贝对象加入到容器中。
#include 
#include 
using namespace std;
class Foo{
private:
    int a;
public:
    Foo(int num): a(num) {
        cout<<"Foo Constructor "< vec1;
    Foo foo1(1);
    vec1.push_back(foo1);

    cout<<1< vec2;
    Foo foo2(2);
    vec2.emplace_back(foo2);
    cout<<2<
push_back:

Foo Constructor 1
copy constructor
1

emplace_back:

Foo Constructor 2
copy constructor
2
Foo Destructor...
Foo Destructor...
Foo Destructor...
Foo Destructor...

  1. 拷贝构造函数和移动构造函数均定义,push_back/emplace_back向容器中加入显式构造的右值元素, 那么均会先后调用构造函数和移动构造函数,再加入到容器中。
#include 
#include 
using namespace std;
class Foo{
private:
    int a;
public:
    Foo(int num): a(num) {
        cout<<"Foo Constructor "< vec1;
    vec1.push_back(Foo(1));

    cout<<1< vec2;
    vec2.emplace_back(Foo(2));
    cout<<2<
push_back:

Foo Constructor 1
move constructor
Foo Destructor...
1

emplace_back:

Foo Constructor 2
move constructor
Foo Destructor...
2
Foo Destructor...
Foo Destructor...