C++两组容器操作的区别:reserve()和resize()、emplace_back()和push_back()
描述
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++容器——vector的reserve()和resize()踩坑记录
-
vector容器resize和reserve方法的区别
-
[c++] push_back和emplace_back的区别
-
C++ emplace_back 和 push_back 的区别
-
C++ STL 容器vector添加元素函数emplace_back()和push_back()的使用差异
-
c++ vector容器emplace_back() 和 push_back 的区别
-
c++ std::vector 使用push_back 和emplace_back的区别
-
c++中STL的push_back和emplace_back的区别
-
C++ vector中push_back()和emplace_back()的区别
-
C++两组容器操作的区别:reserve()和resize()、emplace_back()和push_back()