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


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

    一、区别:

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

    1. push_back()

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

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

    2. emplace_back()

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

    3. 程序示例

    #include <iostream>
    #include <vector>
    using namespace std;
    class Foo{
    private:
        int a;
    public:
        Foo(int num): a(num) {
            cout<<"Foo Constructor "<<a<<endl;
        }
        Foo(){
            cout<<"Default Foo Constructor"<<endl;
        }
        ~Foo() { cout << "Foo Destructor..." << endl; }
        Foo(const Foo& a){
            cout<<"copy constructor"<<endl;
        }
        Foo(const Foo&& a){
            cout<<"move constructor"<<endl;
        }
    };
    
    int main() {
        cout<<endl<<"push_back:"<<endl<<endl;
        vector<Foo> vec1;
        vec1.push_back(1);
    
        cout<<endl<<"emplace_back:"<<endl<<endl;
        vector<Foo> 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 <iostream>
    #include <vector>
    using namespace std;
    class Foo{
    private:
        int a;
    public:
        Foo(int num): a(num) {
            cout<<"Foo Constructor "<<a<<endl;
        }
        Foo(){
            cout<<"Default Foo Constructor"<<a<<endl;
        }
        ~Foo() { cout << "Foo Destructor..." <<endl; }
        Foo(const Foo& foo){
            cout<<"copy constructor"<<endl;
        }
        Foo(const Foo&& foo){
            cout<<"move constructor"<<endl;
        }
    };
    
    int main() {
        cout<<endl<<"push_back:"<<endl<<endl;
        vector<Foo> vec1;
        Foo foo1(1);
        vec1.push_back(foo1);
    
        cout<<1<<endl;
    
        cout<<endl<<"emplace_back:"<<endl<<endl;
        vector<Foo> vec2;
        Foo foo2(2);
        vec2.emplace_back(foo2);
        cout<<2<<endl;
    }
    
    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 <iostream>
    #include <vector>
    using namespace std;
    class Foo{
    private:
        int a;
    public:
        Foo(int num): a(num) {
            cout<<"Foo Constructor "<<a<<endl;
        }
        Foo(){
            cout<<"Default Foo Constructor"<<a<<endl;
        }
        ~Foo() { cout << "Foo Destructor..." <<endl; }
        Foo(const Foo& foo){
            cout<<"copy constructor"<<endl;
        }
        Foo(const Foo&& foo){
            cout<<"move constructor"<<endl;
        }
    };
    
    int main() {
        cout<<endl<<"push_back:"<<endl<<endl;
        vector<Foo> vec1;
        vec1.push_back(Foo(1));
    
        cout<<1<<endl;
    
        cout<<endl<<"emplace_back:"<<endl<<endl;
        vector<Foo> vec2;
        vec2.emplace_back(Foo(2));
        cout<<2<<endl;
    }
    
    push_back:
    
    Foo Constructor 1
    move constructor
    Foo Destructor...
    1
    
    emplace_back:
    
    Foo Constructor 2
    move constructor
    Foo Destructor...
    2
    Foo Destructor...
    Foo Destructor...
    
  • 相关阅读:
    Three.js入门和搭建HelloWorld
    CentOS中使用Docker来部署Tomcat
    CentOS中使用Docker来部署Nginx
    Windows中通过bat定时执行命令和mysqldump实现数据库备份
    Geoserver在Linux上的安装(图文教程)
    Linux上怎样停止服务(jar包)、查看进程路径、关闭指定端口
    Java中怎样监测局域网内ip是否互通,类似ping
    Android和JS之间互相调用方法并传递参数
    Android中使用WebView加载本地html并支持运行JS代码和支持缩放
    ARC072C
  • 原文地址:https://www.cnblogs.com/qiangz/p/15957328.html
Copyright © 2020-2023  润新知