c++ vector容器emplace_back
为在容器操作时尽可能的减少构造函数的调用和内存的拷贝,C++11 引入了emplace_back的方法,该方法可以改善往容器内推入对象元素时的效率。相比push_back,可以节省一次拷贝构造函数的调用从而提高插入效率;
push_back() 向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素);而 emplace_back() 在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程;
push_back()方法要调用构造函数和复制构造函数,这也就代表着要先构造一个临时对象,然后把临时的copy构造函数拷贝或者移动到容器最后面;而emplace_back()在实现时,则是直接在容器的尾部创建这个元素,省去了拷贝或移动元素的过程;
emplace_back()在容器尾部添加一个元素,调用构造函数原地构造,不需要触发拷贝构造和移动构造。在实际使用时,优先选用 emplace_back()。
在调用push_back时,每次执行push_back操作,相当于底层的数组实现要重新分配大小;这种实现体现到vector上,就是每当push_back一个元素,都要重新分配一个大一个元素的存储,然后将原来的元素拷贝到新的存储,之后在拷贝push_back的元素,最后要析构原有的vector并释放原有的内存。如:v.push_back(s1); vector会申请一个内存空间,并调用拷贝构造函数将s1放到vector中;
如果想提高效率时,也可以让容器变为指针容器,到时候直接推入指针变量即可。这样的话,每次推入的代价就由真个类的的拷贝构造函数转为了指针的拷贝,效率会明显提升。
vector<pair<int, int>> ret;
ret.push_back(1,1)//会报错,因为没有构造一个临时对象
ret.push_back(pair(1,1))//不会报错,因为构成了一个pair对象
ret.emplace_back(1,1)//不会报错,因为直接在容器的尾部创建对象
vector<vector<int>> ans;int lastcol = INT_MIN;for (const auto& [col, row, value]: nodes) {if (col != lastcol) {lastcol = col;ans.emplace_back();//这里的emplace_back()直接在ans的尾部创建一个类型为vector<int>的空对象,如果省去这一行,后面的ans.back()会是一个空指针而报错。}ans.back().emplace_back(value);}
测试代码
#include<iostream>
using namespace std;
#include<string>
#include<vector>
class student {
public:student(string s, int a) {cout << "构造函数调用" << endl;name = s;a = age;}student(const student& s ) {cout << "拷贝构造函数调用" << endl;}
private:string name;int age;
};
int main() {vector<student> v;student s1("tom", 12);v.push_back(s1); //需先创建studnet类对象,才能进行插入操作;v.emplace_back("marry", 18); //无需先创建一个student类对象,就可以直接插入一个类对象到vector容器//v.push_back("bob", 19); //会报错,必须先创建一个student类对象,才能进行尾插操作return 0;
}
测试结果输出:当两个插入一起插入时,会触发未知的拷贝构造操作,就会看到两种函数插入方式都调用了拷贝构造函数;
- 单独进行 emplace_back() 操作;当多次插入操作导致vector已满时,就要分配一块更大的内存(比原始大小多50%),将原始数据复制过来并释放之前的内存。原始数据的复制就是这些拷贝构造操作。
- 测试代码
#include<iostream>
using namespace std;
#include<string>
#include<vector>
class student {
public:student(string s, int a) {cout << "构造函数调用" << endl;name = s;a = age;}student(const student& s ) {cout << "拷贝构造函数调用" << endl;}~student() {cout << "析构函数" << endl;}
private:string name;int age=0;
};
int main() {vector<student> v;cout << "初始vector容器大小为:" << v.size() << endl;v.emplace_back("marry", 18); v.emplace_back("tom", 8); //至此vecotr容器满,才需调用拷贝构造函数cout << "vector容器大小为:" << v.size() << endl;v.emplace_back("xiaoming", 28); cout << "vector容器大小为:" << v.size() << endl;v.emplace_back("xiaoming", 8); cout << "vector容器大小为:" << v.size() << endl;return 0;
}
- 测试结果输出;当vector容器填满时,则调用一次拷贝构造函数,并调用析构函数释放原来内存空间;下打印的“拷贝构造函数调用”即vector满时,需要分配更大的内存并复制原始数据而产生的。并且每次分配更大内存时,都比原始大小多50%;
- vector容器:内存空间只会增长,不会减小;为了支持快速的随机访问,vector容器的元素以连续方式存放,每一个元素都紧挨着前一个元素存储。设想一下,当vector添加一个元素时,为了满足连续存放这个特性,都需要重新分配空间、拷贝元素、撤销旧空间;
c++ vector容器emplace_back相关推荐
- STL之序列式容器(三)、vector容器
一.vector的使用.创建及初始化 vector<T> 容器是包含 T 类型元素的序列容器,和 array<T,N> 容器相似,不同的是 vector<T> 容器 ...
- 【STL四】序列容器——vector容器
[STL容器]序列容器--vector容器 一.简介 二.头文件 三.模板类 四.成员函数 1.迭代器 2.元素访问 3.容量 4.修改操作 五.demo 1.容量reserve.capacity.s ...
- C++:vector容器中使用pair该如何访问成员
(显然,vector 的索引从 0 开始,这和普通数组一样.通过使用索引,总是可以访问到 vector 容器中现有的元素.) 如果是简单的访问vector里边的成员的话,是这样的: #include ...
- vector容器中erase(删除)的使用
erase函数可以用于删除vector容器中的一个或者一段元素,在删除一个元素的时候,其参数为指向相应元素的迭代器,而在删除一段元素的时候,参数为指向一段元素的开头的迭代器以及指向结尾元素的下一个元素 ...
- vector容器 begin()与end()函数、front()与back()的用法
begin函数: 函数原型: iterator begin(); const_iterator begin(); 功能: 返回一个当前vector容器中起始元素的迭代器. end函数: 函数原型: i ...
- vector容器中数据的排序方法
前言 在项目中经常会遇到对vector容器中数据排序的情况,有时候vector中数据还常常是pair关联容器.此处给出一个使用demo,使用了C++中的lambda表达式. #include" ...
- vector 容器 动态数组总结
vector 容器 动态数组总结 二话不说直接上代码 #include <vector> #include <algorithm> #include <iostream& ...
- vector容器的用法
转自一篇博客^-^: 1 基本操作 (1)头文件#include<vector>. (2)创建vector对象,vector<int> vec; (3)尾部插入数字:vec.p ...
- vector容器与iterator迭代器
vector容器 vector是同一种类型的对象的集合,每个对象都有一个对应的整数索引值.和string对象一样,标准库负责管理存储元素的相关内存.我们把vector称为容器,是因为它可以包含其他对象 ...
- 【C++ 语言】vector 容器 ( 容器分类 | vector 声明 | vector 初始化 | vector 容器元素增删查改 )
文章目录 序列式容器 vector 简介 vector ( 向量 ) 头文件 vector ( 向量 ) 声明及初始化 vector ( 向量 ) 添加元素 vector ( 向量 ) 查询元素 ve ...
最新文章
- golang变量的数据类型:整型及其使用细节
- Integration testing
- .NET访问PI数据库
- RPMB原理介绍【转】
- 2 追踪光线=》2.2 前向光线追踪和逆向光线追踪
- python封装sql脚本_flask-sqlalchemy如何使用原生的sql语句然后封装?
- npm ERR! Unexpected end of JSON input while parsing near '...Comment: https://open'
- pyglet: a cross-platform windowing and multimedia
- select的使用及缺陷
- 数学建模大赛准备方法及资源分享
- Get Server Down when retrieve the channel list in sopcast, how to solve it?
- mysql外文文献中英文3千字_MySQL数据库管理外文中英文翻译文献.doc
- sscanf 实现_医保 | 好消息!门诊慢病实现山东省内联网结算啦~
- 百分点大数据技术团队:互联网舆情系统的架构实践
- 什么样的视频号内容更容易火?视频号怎么做推送上热门
- Python性能分析利器pyinstrument讲解
- MATLAB设置起始文件夹
- Unicode中的UTF-8, UTF-16, UTF-16LE, UTF-16BE编码及转换 | Java基础
- [洛谷P4233]射命丸文的笔记
- 《奇点来临》——镜子测试与认知