百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

C++中STL常见问题汇总,越来越熟悉STL底层原理和应用(2)

liebian365 2024-10-25 15:40 20 浏览 0 评论

STL中迭代器什么时候会失效?

  • 对于序列容器vector,deque来说,使用erase后,后边的每个元素的迭代器都会失效,后边每个元素都往前移动一位,erase返回下一个有效的迭代器

说明

当删除一个元素后,内存中的数据会发生移动以保证数据的紧凑。所以删除一个元素后,其他数据的地址发生了变化,之前获取的迭代器根据原有信息就访问不到正确的数据。

//迭代器失效
void vectorTest()
{
    vector<int> container;
    for (int i = 0; i < 10; i++)
    {
        container.push_back(i);
    }
 
    vector<int>::iterator iter;
     for (iter = container.begin(); iter != container.end(); iter++)
    {
            if (*iter > 3)
              container.erase(iter);
    }
 
     for (iter = container.begin(); iter != container.end(); iter++)
    {
            cout<<*iter<<endl;
    }
}

//代码修改,ok
	void vectorTest()
{
    vector<int> container;
    for (int i = 0; i < 10; i++)
    {
        container.push_back(i);
    }
 
    vector<int>::iterator iter;
     for (iter = container.begin(); iter != container.end();)
    {
            if (*iter > 3) {
				iter = container.erase(iter);
			}
			else {
				iter ++;
			}
    }
 
     for (iter = container.begin(); iter != container.end(); iter++)
    {
            cout<<*iter<<endl;
    }
}
  • 对于关联容器map,set来说,使用了erase后,当前元素的迭代器失效,但是其结构是红黑树,删除当前元素,不会影响下一个元素的迭代器,所以在调用erase之前,记录下一个元素的迭代器即可。

说明:

虽然删除了一个元素,整棵树也会调整,以符合红黑树规范,但是单个节点在内存中的地址没有变化,变化的是各节点之间的指向关系。删除一个结点不会对其他结点造成影响。 erase迭代器只是被删元素的迭代器失效。

#include<iostream>
#include<string>
#include<map>
using namespace std;

int main()
{
    map<string, int> mapData;
    mapData["a"] = 1;
    mapData["b"] = 2;
    mapData["c"] = 3;

    map<string, int>::iterator itMap = mapData.begin();
    while (itMap != mapData.end())
    {
        if (strcmp(itMap->first.c_str(), "a") == 0)
        {
            mapData.erase(itMap++);
        }
        else
        {
            itMap++;
        }

        /* 迭代器失效
        if (strcmp(itMap->first.c_str(), "a") == 0)
        {
            mapData.erase(itMap);
        }
        itMap++;
        */
    }
}
  • list来说,它使用了不连续分配的内存,并且它的erase方法也会返回下一个有效的迭代器

上面两种方法都可以使用。

STL中迭代器的作用,有指针为何还要迭代器?

  • 迭代器作用

(1)用于指向顺序容器和关联容器中的元素。

(2)通过迭代器可以读取它指向的元素。

(3)通过非const迭代器可以修改其指向的元素。

  • 迭代器和指针的区别

迭代器不是指针,是类模板,表现得像指针。迭代器模拟了指针的一些功能,重载了指针的一些操作符。迭代器本质是封装了原生指针,是指针概念的一种提升,提供了比指针更高级的行为,可以看成一种智能指针,他可以根据不同类型的数据结构来实现不同的++,--等操作。

  • 迭代器产生的原因

Iterator类的访问方式就是把不同集合类的访问逻辑抽象出来,使得不用暴露集合内部的结构而达到循环遍历集合的效果。

STL 迭代器是怎么删除元素的

这主要考察迭代器失效的问题,上面已经总结。

STL 中 resize 和 reserve 的区别

  • 两个概念

(1)capacity:该值在容器初始化时赋值,指的是容器能够容纳的最大的元素的个数。还不能通过下标等访问,因为此时容器中还没有创建任何对象。

(2)size:指的是此时容器中实际的元素个数。可以通过下标访问0-(size-1)范围内的对象。

  • resize和reserve区别

(1)resize既分配了空间,也创建了对象reserve表示容器预留空间,但并不是真正的创建对象,需要通过insert()或push_back()等创建对象。

(2)resize既修改capacity大小,也修改size大小;reserve只修改capacity大小,不修改size大小

(3)两者的形参个数不一样。 resize带两个参数,一个表示容器大小,一个表示初始值(默认为0);reserve只带一个参数,表示容器预留的大小。

STL 容器动态链接可能产生的问题?

  • 可能会产生什么问题

容器是一种动态分配内存空间的一个集合类型的变量。在一般的程序函数里,局部容器,参数传递容器,参数传递容器的引用,参数传递容器指针都是可以正常运行的,而在动态链接库函数内部使用容器也是没有问题的,但是给动态库函数传递容器的对象本身,则会出现内存堆栈破坏的问题。

  • 产生问题原因

容器和动态链接库相互支持不够好,动态链接库函数中使用容器时,参数中只能传递容器的引用,并且要保证容器的大小不能超出初始大小,否则导致容器自动重新分配,就会出现内存堆栈破坏问题

map 和 unordered_map 的区别?底层实现

  • map实现机理

map内部实现了一个红黑树红黑树有自动排序的功能,因此map内部所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。对于map进行的查找、删除、添加等一系列的操作都相当于是对红黑树进行的操作。map中的元素是按照二叉查找树存储的(左子树上所有节点的键值都小于根节点的键值,右子树所有节点的键值都大于根节点的键值)。中序遍历可将键值按照从小到大遍历出来

  • unordered_map实现机理

unordered_map内部实现了一个哈希表,通过把关键码值映射到Hash表中一个位置来访问记录,查找时间复杂度可达O(1),在海量数据处理中有着广泛应用。因此,元素的排列顺序是无序的。

push_back 和 emplace_back 的区别

要将一个临时变量push到容器的末尾,push_back()需要先构造临时对象,再将这个对象拷贝到容器的末尾,而emplace_back()则直接在容器的末尾构造对象,这样就省去了拷贝的过程。

#include<iostream>
using namespace std;
#include<string>
#include<vector>

class TestA
{
public:
	string str;
	TestA(int i)
	{
		str = to_string(i);
		cout << "构造函数的调用" << endl;
	}

	~TestA()
	{
		//cout << "析构函数的调用" << endl;
	}

	TestA(const TestA& other) :str(other.str)
	{
		cout << "拷贝函数构造" << endl;
	}

};

int main()
{
	vector< TestA> vec;
	vec.reserve(10);
	for (int i = 0; i < 10; i++)
	{
		//调用了10次构造函数和10次拷贝构造函数
		vec.push_back(i);

		//调用了10次构造函数,没有调用拷贝构造函数
		//vec.emplace_back(i);
	}
	return 0;
}

push_back()运行结果:


emplece_back()运行结果:


相关推荐

4万多吨豪华游轮遇险 竟是因为这个原因……

(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

“菜鸟黑客”必用兵器之“渗透测试篇二”

"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

每日新闻播报(September 14)_每日新闻播报英文

AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

香港新巴城巴开放实时到站数据 供科技界研发使用

中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

Qt动画效果展示_qt显示图片

今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

如何从0到1设计实现一门自己的脚本语言

作者:dong...

三年级语文上册 仿写句子 需要的直接下载打印吧

描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

C++|那些一看就很简洁、优雅、经典的小代码段

目录0等概率随机洗牌:1大小写转换2字符串复制...

二年级上册语文必考句子仿写,家长打印,孩子照着练

二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

一年级语文上 句子专项练习(可打印)

...

亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

...

取消回复欢迎 发表评论: