std::vector

这里主要介绍下reserce/resize、push_back/emplace_back、shrink_to_fit/clear等接口;

1. reserve and resize

       C++的vector对象可以通过reserve方法来设置vector对象的容量,通过resize方法来改变vector对象的大小。reserve所设置的容量指的是vector容器中可容纳元素的预留空间个数,但并不真正创建元素对象。resize则是直接改变vector容器中元素的个数,并且创建对象或者销毁空间。

       resize()函数和容器的size息息相关。调用resize(n)后,容器的size即为n。至于是否影响capacity,取决于调整后的容器的size是否大于capacity。

reserve()函数和容器的capacity息息相关。调用reserve(n)后,若容器的capacity<n,则重新分配内存空间,从而使得capacity等于n。

如果capacity>=n呢?capacity无变化。

       从两个函数的用途可以发现,容器调用resize()函数后,所有的空间都已经初始化了,所以可以直接访问。

        而reserve()函数预分配出的空间没有被初始化,所以不可访问。

#include <iostream>
#include <vector>
#include <string>
#include <map>using ValueType = std::string;
const ValueType dv = "aaaaaaaaaaaaaaaaaaaaaaaa";
constexpr int maxSize = 10;class Widget {
public:Widget(ValueType value = dv) : value{value}{std::cout << "Widget(ValueType) constructor: " << this << std::endl;}Widget(const Widget& w) : value{w.value}{std::cout<<"copy constructor" << std::endl;}Widget& operator=(const Widget& rhs){if (this != &rhs){value = rhs.value;//assign new resource}std::cout << "copy assignment constructor" << std::endl;return *this;}//这里移动构造函数定义为noexceptWidget(Widget&& w) noexcept: value{std::move(w.value)}{std::cout << "move constructor" << std::endl;}Widget& operator=(Widget&& rhs){if (this != &rhs){value = std::move(rhs.value);//assign new resource}std::cout << "move assignment constructor" << std::endl;return *this;}~Widget(){if (value.empty()){std::cout << "0~destructor:" << this << std::endl;}else{value.clear();std::cout << "~destructor:" << this << std::endl;}}void print(){std::cout << "value:" << value << " : " << this << std::endl;}
private:ValueType value{};
};void test_reserve()
{std::vector<Widget> v{Widget{"aaaaaaaaaaaaaaaaaaaaaaaa"}, Widget{"bbbbbbbbbbbbbbbbbbbbbbbb"}, Widget{"ccccccccccccccccccccccc"}};std::cout << "size()=" << v.size() << ", capacity()=" << v.capacity() << std::endl << std::endl;v.reserve(2);//当reserve的数据空间小于capacity的时候什么都不做;std::cout << "size()=" << v.size() << ", capacity()=" << v.capacity() << std::endl << std::endl;//当reserve的数据空间大于capacity时,vector的capacity变为reserve指定的大校v.reserve(5);//由于要重新分配比 3 更大的存储空间,这里再次调用的移动构造函数(如果移动构造函数没有noexcept,则调用拷贝构造函数)std::cout << "size()=" << v.size() << ", capacity()=" << v.capacity() << std::endl << std::endl;v.reserve(4);std::cout << "size()=" << v.size() << ", capacity()=" << v.capacity() << std::endl << std::endl;v.reserve(2);std::cout << "size()=" << v.size() << ", capacity()=" << v.capacity() << std::endl << std::endl;
}void test_resize()
{std::vector<Widget> v{Widget{"aaaaaaaaaaaaaaaaaaaaaaaa"}, Widget{"bbbbbbbbbbbbbbbbbbbbbbbb"}, Widget{"ccccccccccccccccccccccc"}};std::cout << std::endl;std::cout << "size()=" << v.size() << ", capacity()=" << v.capacity() << std::endl << std::endl;v.resize(5);//vector重新分配空间(需要移动/拷贝原数据),resize的空间大于size()时,会构造 5 - size()个数据项(这里是构造2个新的Widget)std::cout << "size()=" << v.size() << ", capacity()=" << v.capacity() << std::endl << std::endl;v.resize(4);//destory多余指定size的数据项std::cout << "size()=" << v.size() << ", capacity()=" << v.capacity() << std::endl << std::endl;v.resize(2);//destory多余指定size的数据项std::cout << "size()=" << v.size() << ", capacity()=" << v.capacity() << std::endl << std::endl;
}int main()
{test_reserve();std::cout << "----------------------" << std::endl;test_resize();return 0;
}

output:

2. vector(count, value) vs reserve(n)

这里有一个点需要注意下:vector( size_type count,

                                                        const T& value, 

                                                        const Allocator& alloc = Allocator() );

和 vector.reserve的区别, 这个vector会构造数据项,而reserve不构造数据项,只是预留了空间;

#include <iostream>
#include <vector>void test_vector_constructor_vs_reserve()
{std::vector<int> v1(2,3);std::cout << "size()=" << v1.size() << ", capacity()=" << v1.capacity() << std::endl << std::endl;for(const auto i : v1){std::cout << i << ' ';}std::cout << std::endl;std::vector<int> v2{};v2.reserve(2);//当reserve的数据空间小于capacity的时候什么都不做;std::cout << "size()=" << v2.size() << ", capacity()=" << v2.capacity() << std::endl << std::endl;
}int main()
{test_vector_constructor_vs_reserve();return 0;
}

 3. shrink_to_fit vs clear

shrink_to_fit() : 它减少容器的容量以适应其大小并销毁超出容量的所有元素。

clear():从容器擦除所有元素。此调用后 size() 返回零。使任何指代所含元素的引用、指针或迭代器失效。任何尾后迭代器也会失效。  保持 vector 的 capacity() 不变。

#include <iostream>
#include <vector>
#include <string>using ValueType = std::string;
const ValueType dv = "aaaaaaaaaaaaaaaaaaaaaaaa";
constexpr int maxSize = 10;class Widget {
public:Widget(ValueType value = dv) : value{value}{std::cout << "Widget(ValueType) constructor: " << this << std::endl;}Widget(const Widget& w) : value{w.value}{std::cout<<"copy constructor" << std::endl;}Widget& operator=(const Widget& rhs){if (this != &rhs){value = rhs.value;//assign new resource}std::cout << "copy assignment constructor" << std::endl;return *this;}//这里移动构造函数定义为noexceptWidget(Widget&& w) noexcept: value{std::move(w.value)}{std::cout << "move constructor" << std::endl;}Widget& operator=(Widget&& rhs){if (this != &rhs){value = std::move(rhs.value);//assign new resource}std::cout << "move assignment constructor" << std::endl;return *this;}~Widget(){if (value.empty()){std::cout << "0~destructor:" << this << std::endl;}else{value.clear();std::cout << "~destructor:" << this << std::endl;}}void print(){std::cout << "value:" << value << " : " << this << std::endl;}
private:ValueType value{};
};void test_shrink_to_fit()
{std::vector<Widget> v;std::cout << "size()=" << v.size() << ", capacity()=" << v.capacity() << std::endl << std::endl;v.emplace_back(std::string(24, 'a'));v.emplace_back(std::string(24, 'b'));v.emplace_back(std::string(24, 'c'));v.emplace_back(std::string(24, 'd'));v.emplace_back(std::string(24, 'e'));std::cout << "size()=" << v.size() << ", capacity()=" << v.capacity() << std::endl << std::endl;v.shrink_to_fit();//按照我测试结果,测试capacity=8, size为添加的5个元素;//shrink_to_fit会释放掉多余的vector空间,使得capacity()==size();//这里可能会重新分配空间,具体依赖于编译器的实现std::cout << "size()=" << v.size() << ", capacity()=" << v.capacity() << std::endl << std::endl;
}void test_clear()
{std::vector<Widget> v{Widget{"aaaaaaaaaaaaaaaaaaaaaaaa"}, Widget{"bbbbbbbbbbbbbbbbbbbbbbbb"}, Widget{"ccccccccccccccccccccccc"}};std::cout << "size()=" << v.size() << ", capacity()=" << v.capacity() << std::endl << std::endl;std::cout << "call clear():" << std::endl;;v.clear();//会把所有数据项destory掉,此时size()大小为0, capacity则不变;std::cout << "size()=" << v.size() << ", capacity()=" << v.capacity() << std::endl << std::endl;}int main()
{test_shrink_to_fit();std::cout << std::endl << "----------------------" << std::endl << std::endl;test_clear();return 0;
}

4. push_back vs emplace_back

push_back:是插入数据到vector,这里会构造一个临时的数据项,这个临时数据项参数满足push_back(T&& value)接口,通过移动构造函数把这个临时的数据项移动到vector对应的位置上;

emplace_back:是通过完美转发参数,在vector对应的位置上就地构造,只需要调用一次构造函数就可以;这种情况下,效率上来说要比push_back高一些;

对于push_back和emplace_back来说,如果传入的数据项本身是个左值,那么他们效率上都是一样的。因为这两个接口都只需要调用一次拷贝构造函数。代码如下:

#include <iostream>
#include <vector>
#include <string>
#include <map>using ValueType = std::string;
const ValueType dv = "aaaaaaaaaaaaaaaaaaaaaaaa";
constexpr int maxSize = 10;class Widget {
public:Widget(ValueType value = dv) : value{value}{std::cout << "Widget(ValueType) constructor: " << this << std::endl;}Widget(const Widget& w) : value{w.value}{std::cout<<"copy constructor" << std::endl;}Widget& operator=(const Widget& rhs){if (this != &rhs){value = rhs.value;//assign new resource}std::cout << "copy assignment constructor" << std::endl;return *this;}Widget(Widget&& w) : value{std::move(w.value)}{std::cout << "move constructor" << std::endl;}Widget& operator=(Widget&& rhs){if (this != &rhs){value = std::move(rhs.value);//assign new resource}std::cout << "move assignment constructor" << std::endl;return *this;}~Widget(){if (value.empty()){std::cout << "0~destructor:" << this << std::endl;}else{value.clear();std::cout << "~destructor:" << this << std::endl;}}void print(){std::cout << "value:" << value << " : " << this << std::endl;}
private:ValueType value{};
};
void push_vs_empalce_with_rvalue_item()
{std::vector<Widget> v{};v.reserve(10);std::cout << std::endl;std::string str(24, 'a');v.push_back(str);std::cout << std::endl;v.emplace_back(str);std::cout << std::endl;}
void push_vs_empalce_with_lvalue_item()
{Widget w1("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");Widget w2("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");std::vector<Widget> v{};v.reserve(10);std::cout << std::endl;v.push_back(w1);std::cout << std::endl;v.emplace_back(w2);std::cout << std::endl;
}int main()
{push_vs_empalce_with_rvalue_item();std::cout << std::endl << "-------------------------" << std::endl << std::endl;push_vs_empalce_with_lvalue_item();return 0;
}

output:

 

后续再介绍vector插入数据的性能等;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/221787.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网工内推 | IT经理,50k*14薪,NP以上即可,七险一金

01 海天瑞声 招聘岗位&#xff1a;IT经理 职责描述&#xff1a; 1、IT基础架构的方案制定、实施和日常维护&#xff0c;包括机房建设运维、服务器配置及运维、网络规划及运维、上网行为管理、电话、电话、监控、门禁等各类弱电系统搭建及运维 2、负责公司环境及网络安全防御体…

Vue 按键修饰符

常用按键修饰符&#xff1a;enter【回车】、delete【删除】、esc【退出】、space【空格】、tab【缩进】、up【上】、down【下】、left【左】、right【右】 。 系统按键修饰符&#xff1a;ctrl、alt、shift、meta【四个小方块】 。 鼠标修饰符&#xff1a;left【左键】、right…

Chip and Ribbon Educational Codeforces Round 158 (Rated for Div. 2)

Problem - B - Codeforces 题目大意&#xff1a;有一个n个数的数组a&#xff0c;有一个初始等于1的指针&#xff0c;有两种操作&#xff1a; 1.设指针当前位置为l&#xff0c;可以选择一个任意位置r(r>l)&#xff0c;使[l,r]内所有数1 2.将指针移动到一个任意位置&#x…

ubuntu 自动安装 MKL Intel fortran 编译器 ifort 及完美平替

首先据不完全观察&#xff0c;gfortran 与 openblas是 intel fortran 编译器 ifotr和mkl的非常优秀的平替&#xff0c;openblas连函数名都跟mkl一样&#xff0c;加了一个下划线。 1&#xff0c; 概况 https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-too…

配电房电力智能运维系统

配电房电力智能运维系统是一种采用先进的信息技术手段&#xff0c;对配电房的电力设备进行实时监控、数据分析和管理的系统。它能够提高电力设备的安全性和效率&#xff0c;降低运维成本&#xff0c;为用户提供更加优质、高效的电力服务。 该系统依托智能运维工具-电易云&#…

PCL点云处理之反算两块点云的放缩比例 (二百二十三)

PCL点云处理之反算两块点云的放缩比例 (二百二十三) 一、算法介绍二、算法实现1.代码2.结果一、算法介绍 在 PCL点云处理之等比例放大与缩小点云尺寸(七十二)一章中,介绍了如何等比例放大缩小一块点云,这里介绍如何反算得到两片经过放缩的点云之间的比例,这种计算方法应…

关系型数据库和非关系型数据库有什么区别?

一、什么是数据库&#xff1f; 数据库是一个结构化的数据集合&#xff0c;用于存储、管理和组织数据。它是一个电子化的文件柜&#xff0c;可以存储大量的数据&#xff0c;并提供了一种高效地检索、更新和管理数据的方法。数据库可以用于存储各种类型的数据&#xff0c;例如文…

【排序算法】之归并排序

归并思想 先拆分后合并 也就是分治&#xff1b; 拆分合并思想具体讲解可以参考以下链接&#xff1a; b站链接&#xff1a; 点这里&#xff1a;b站归并思想具体讲解 看代码 代码中的例子参考上图和下图 public class MergeSort {//一、拆分部分public static void split(i…

springcloud getway 网关之过滤器filter

1. Filter的使用 filter是Gateway的三大核心之一&#xff0c;路由过滤器可用于修改进入HTTP请求和返回的HTTP响应&#xff0c;路由过滤器只能指定路由进行使用。Gateway内置了多种路由过滤器&#xff0c;他们都由GatewayFilter工程 2. Filter的作用 当我们有很多个服务时&am…

【机器学习 | 假设检验系列】假设检验系列—卡方检验(详细案例,数学公式原理推导),最常被忽视得假设检验确定不来看看?

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

2024 年,新程序员如何与AI共赢!!

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

如何在Facebook Business Manager进行企业认证

Facebook Business Manager&#xff0c;简称BM&#xff0c;按照字面意思理解就是Facebook官方的商务管理平台&#xff0c;是供广告主团队去使用的一个管理工具。BM可以绑定Facebook公共主页、广告账户等一系列Facebook账号。通过BM&#xff0c;企业就可以在一个后台&#xff0c…

Amazon SageMaker: 拓展机器学习边界,塑造未来创新趋势

授权说明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 亚马逊云科技开发者社区, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道。 近期在 re:Invent 2023 大会上&#xff0c;亚马逊云科技发布了一…

Stable Diffusion 源码解析(1)

参考1&#xff1a;https://blog.csdn.net/Eric_1993/article/details/129393890 参考2&#xff1a;https://zhuanlan.zhihu.com/p/613337342 1.StableDiffusion基本原理1.1 UNetModel、FrozenCLIP 模型1.2 DDPM、DDIM、PLMS算法 2. Runwayml SD 源码2.1 Img2Img Pipeline2.2 DD…

蚁群优化算法ACO

蚁群优化算法模拟了自然界中蚂蚁的觅食行为&#xff0c;信息素浓度的大小表征路径的远近&#xff0c;信息素浓度越高&#xff0c;表示对应的路径距离越短。同时&#xff0c;路径上的信息素浓度会随着时间的推进而逐渐衰减。 1.过程 &#xff08;1&#xff09;初始化参数 蚁群…

Nginx+Tomcat实现负载均衡和动静分离

目录 前瞻 动静分离和负载均衡原理 实现方法 实验&#xff08;七层代理&#xff09; 部署Nginx负载均衡服务器(192.168.75.50:80) 部署第一台Tomcat应用服务器&#xff08;192.168.75.60:8080&#xff09; 多实例部署第二台Tomcat应用服务器&#xff08;192.168.75.70:80…

8080端口被占用怎么解决,并结束释放8080端口

8080端口是被用于WWW代理服务的&#xff0c;可以实现网页浏览&#xff0c;经常在访问某个网站或使用代理服务器的时候&#xff0c;Win10 8080端口被占用解决方法吧。 1、按【 Win r】 2、运行窗口&#xff0c;输入【cmd】命令&#xff0c;按【确定或回车】&#xff0c;打开命…

基于SpringBoot 校园招聘系统设计与实现(源码+文档+可视化HTML+数据库)

摘 要 基于SpringBoot 校园招聘系统是一种基于Java技术的校园招聘和可视化展示的系统。该系统通过采集和整合各类招聘网站、社交媒体等渠道的数据&#xff0c;对招聘岗位进行深入分析&#xff0c;并将分析结果以直观、易懂的可视化形式呈现。系统能够自动从多个数据源获取招聘…

电子学会C/C++编程等级考试2023年03月(五级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:拼点游戏 C和S两位同学一起玩拼点游戏。有一堆白色卡牌和一堆蓝色卡牌,每张卡牌上写了一个整数点数。C随机抽取n张白色卡牌,S随机抽取n张蓝色卡牌,他们进行n回合拼点,每次两人各出一张卡牌,点数大者获得三颗巧克力,小者获…

Flutter:web项目跨域问题解决

前后端解决系列 文章目录 一、Flutter web客户端解决本地环境调试跨域问题二、Flutter web客户端解决线上环境跨域问题 一、Flutter web客户端解决本地环境调试跨域问题 就一句命令【--web-browser-flag "--disable-web-security"】&#xff0c;用来屏蔽浏览器域名请…