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

C++两组容器操作的区别:reserve()和resize()、emplace_back()和push_back()

程序员文章站 2022-03-01 23:19:45
...

描述

C++执行容器(vector,map等)操作时,总有一些需求,比如说设置容器大小啊,增加元素啊。

这里介绍两组写法的区别,设置容器大小的reserve()和resize()、添加元素的emplace_back()和push_back()

1. reserve()和resize()

这个比较简单。

  • reserve()增加了vector的capacity,但是它的size没有改变
  • resize()改变了vector的capacity,同时也增加了它的size!

原因如下:

reserve是容器预留空间,但在空间内不真正创建元素对象,所以在没有添加新的对象之前,不能引用容器内的元素。加入新的元素时,要调用push_back()/insert()函数。

resize是改变容器的大小,且在创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。此时再调用push_back()函数,是加在这个新的空间后面的。

最后面一节是resize和reserve的一些例子,这里我还是给出我的总结

当我们写代码时
当我们已知这个向量的大小时

vector<int> vect;
vect.resize(100); // 比如你已知大小为100
for (int i = 0 ; i < 100 ; i++)
{
	vect[i] = i;  // 建议你一个一个赋值
}

当我们不确定这个向量要存多少变量时

vector<int> vect;
vect.push_back(1); // 你可以一直push_back
cout<<vect.size()<<endl; // 向量的实际大小

2. emplace_back()和push_back()

总结,一般情况下,请你使用push_back(),不要使用emplace_back()

使用emplace_back()的唯一好处就是,你可以不创建对象,就可以向容器里增加一个对象。一般来说,emplace_back()函数要比push_back()函数要快一倍。

push_back() 在底层实现时,会优先选择调用移动构造函数,如果没有才会调用拷贝构造函数。显然完成同样的操作,push_back() 的底层实现过程比 emplace_back() 更繁琐,换句话说,emplace_back() 的执行效率比 push_back() 高。

举例子

#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(std::move(p_name)), country(std::move(p_country)), year(p_year)  
    {  
        std::cout << "I am being constructed.\n";  
    }
    President(const President& other)
        : name(std::move(other.name)), country(std::move(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);  
};  
 
int main()  
{  
    std::vector<President> elections;  
    std::cout << "emplace_back:\n";  
    elections.emplace_back("Nelson Mandela", "South Africa", 1994); // 可以不创建类 
 
    std::vector<President> reElections;  
    std::cout << "\npush_back:\n";  
    reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936));  
}

程序运行结果为

emplace_back:
I am being constructed.

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

例子

vector<int> myVec;
myVec.reserve( 100 );     // 新元素还没有构造, 此时不能用[]访问元素
for (int i = 0; i < 100; i++ )
{ 
     myVec.push_back( i ); //新元素这时才构造
}
myVec.resize( 102 );      // 用元素的默认构造函数构造了两个新的元素
myVec[100] = 1;           //直接操作新元素
myVec[101] = 2;  
vector<int> vect;
vect.push_back(1);
vect.push_back(2);
vect.push_back(3);
vect.push_back(4);
vect.reserve(100);
cout<<vect.size()<<endl;  //size为4
cout<<vect.capacity()<<endl;  //capacity为100
vector<int> vect;    
vect.push_back(1);
vect.push_back(2);
vect.push_back(3);
vect.push_back(4);
vect.resize(100);    
cout<<vect.size()<<endl;  //size为100
cout<<vect.capacity()<<endl;  //capacity为100
vector<int> vect;        
vect.resize(100);    //分配100个空间
vect.push_back(1);
vect.push_back(2);
vect.push_back(3);
vect.push_back(4);
std::cout<<vect.size()<<std::endl; //现在size为104, 
std::cout<<vect.capacity()<<std::endl; //但是capacity不一定是104,vector会自增长预留空间的.
std::cout<<vect[0]<<std::endl; // vect[0]~vect[99]是0
std::cout<<vect[100]<<std::endl; // 1
std::cout<<vect[101]<<std::endl; // 2
std::cout<<vect[102]<<std::endl; // 3
std::cout<<vect[103]<<std::endl; // 4
相关标签: C++ c++