欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vector中push_back和emplace_back区别

程序员文章站 2022-03-01 22:18:03
...

vector中push_back和emplace_back区别

正常情况下push_back是往vector中添加新的元素,只不过添加过程是先利用拷贝构造函数复制目标值,而 emplace_back可以 直接在目标位置上生成对象,这也正式emplace的原本放置的意思。
具体在使用上,如果push的对象元素是已经生成好了的(如Nelson),emplace_back和push_back可以认为没有区别,如果原本没有要push的这个元素,则直接原地生成效率较高;

实际在push的时候,由于vector内存需要连续,在vector size达到1, 2,4,8…时其长度需要自动增加,故四二次push时首先生成目标元素,检测到现有存储空间已满,会调用复制构造函数来重头到尾复制前面的vector元素,依次push进去vector之后再析构掉复制的元素,最后再将目标元素push进去;

一般移动构造函数的输入为右值,操作完成后右值内容就为空了(数字除外),具体过程可由std::move(左值) 进行模仿.
如果传入的为右值但没有定义移动构造函数,则可调用拷贝构造函数。即emplace_back和push_back均可接收左值(普通变量)和右值(无名临时对象),左值调用复制构造函数,右值调用移动构造函数,表现一致;

    President joy("joy ", "USA", 2021);
    elections.emplace_back(std::move(joy));
    elections.emplace_back(std::move(joy));
    elections.emplace_back(std::move(joy));
//输出结果
joy  elected president of USA in 2021.
	  elected president of 		   in 2021.
 	  elected president of 		   in 2021.

emplace_back结果
elections.emplace_back(“Nelson Mandela”, “South Africa”, 1994)
I am being constructed.
elections.emplace_back(Nelson);
I am being constructed.
I am being copy constructed.
moved:
joy USA2021
elections.emplace_back(std::move(Nelson));
I am being constructed.
I am being moved.
moved:
2021

push_back结果
reElections.push_back(President(“Franklin Delano Roosevelt”, “the USA”, 1936))
I am being constructed.
I am being moved.
I am being destructed.
reElections.push_back(obama);
I am being constructed.
I am being copy constructed.
moved:
Franklin USA1966
reElections.push_back(std::move(obama));
I am being constructed.
I am being moved.
moved:
1966

区别测试代码

这里是参考博客 ().

// An highlighted block
#include <vector>  
#include <string>  
#include <iostream>  

struct President  
{  
    std::string name;  
    std::string country;  
    int year;  

    President(std::string p_name, std::string p_country, int p_year)	//构造函数
    :name(p_name), country(p_country), year(p_year)  
    {  std::cout << "I am being constructed.\n"; }
    
    President(const President& other)	//拷贝构造函数
    :name(other.name), country(other.country), year(other.year)
    { std::cout << "I am being copy constructed.\n";}
    
    President(President&& other)		//移动构造函数
    :name(std::move(other.name)), country(std::move(other.country)), year(other.year)  
    { std::cout << "I am being moved.\n"; }  
    
    President& operator=(const President& other);  
    
    ~President()
    { std::cout << "I am being destructed.\n";} 
};  

int main()  
{  
    std::vector<President> elections;  
    std::cout << "emplace_back:\n";  
    elections.emplace_back("Nelson ", "frica", 1994); //没有类的移动
    elections.emplace_back("Nelson ", "Africa", 1995); 
    elections.emplace_back("Nelson ", "Africa", 1996); 
        President joy("joy ", "USA", 2021);
    elections.emplace_back(std::move(joy));

    
    std::vector<President> reElections;  
    std::cout << "\npush_back:\n";  
    reElections.push_back(President("Franklin ", "USA", 1936));  
    reElections.push_back(President("Franklin ", "USA", 1937));
    reElections.push_back(President("Franklin ", "USA", 1938));
    
    President obama("obama ", "USA", 1966);
    reElections.push_back(obama);
    std::cout << "moved:\n" << obama.name
         << obama.country << obama.year <<std::endl;
    std::cout << "\nContents:\n";  
    for (President const& president: elections) {  
       std::cout << president.name << " elected president of "  
            << president.country << " in " << president.year << ".\n";  
    }  
    for (President const& president: reElections) {  
        std::cout << president.name << " re-elected president of "  
            << president.country << " in " << president.year << ".\n";  
    }
}

结果输出
emplace_back:
I am being constructed.
I am being constructed.
I am being copy constructed.
I am being destructed.
I am being constructed.
I am being copy constructed.
I am being copy constructed.
I am being destructed.
I am being destructed.

push_back:
I am being constructed.
I am being moved.
I am being destructed.
I am being constructed.
I am being moved.
I am being copy constructed.
I am being destructed.
I am being destructed.
I am being constructed.
I am being moved.
I am being copy constructed.
I am being copy constructed.
I am being destructed.
I am being destructed.
I am being destructed.

Contents:
Nelson elected president of frica in 1994.
Nelson elected president of Africa in 1995.
Nelson elected president of Africa in 1996.
Franklin re-elected president of USA in 1936.
Franklin re-elected president of USA in 1937.
Franklin re-elected president of USA in 1938.
I am being destructed.
I am being destructed.
I am being destructed.
I am being destructed.
I am being destructed.
I am being destructed.

vector空间自动增长测试代码

#include <iostream>
#include <vector>

using std::cout; 
using std::endl;

struct X{
    X(int a) {x=a;cout << "调用构造函数:X()" << a << endl;}
    X(const X& Xa) {x=Xa.x; cout << "调用拷贝构造函数:X(const X&)" << x << endl;}
    ~X(){cout << "调用析构函数:~X()" << x << endl;}
	int x;
};

int main(int argc, char **argv)
{
    cout << "定义局部变量:" << endl;
    X x(1);
	X y(2);

    std::vector<X> vec;
    cout << "\n存放在容器:" << endl;
    vec.push_back(y);
	vec.push_back(x);
	vec.push_back(y);
    cout << endl;

    cout << "程序结束!!!" << endl;
    return 0;
}

输出结果

定义局部变量:
调用构造函数:X()1
调用构造函数:X()2
存放在容器:
调用拷贝构造函数:X(const X&)2
调用拷贝构造函数:X(const X&)1
调用拷贝构造函数:X(const X&)2
调用析构函数:~X()2
调用拷贝构造函数:X(const X&)2
调用拷贝构造函数:X(const X&)2
调用拷贝构造函数:X(const X&)1
调用析构函数:~X()2
调用析构函数:~X()1
程序结束!!!
调用析构函数:~X()2
调用析构函数:~X()1
调用析构函数:~X()2
调用析构函数:~X()2
调用析构函数:~X()1

相关标签: code