栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ map/unordered

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ map/unordered

在开发的过程中需要遍历一个unordered_map然后把他的迭代器传给另一个对象:

class A;
class B {
public:
	void deal(const std::pair& item);
};
std::unordered_map mp;
B b;
for (auto &pr : mp) {
	b.deal(pr);
}

在我的项目中A类管理了系统资源,我震惊地发现经过deal函数处理后A类所管理的资源会被释放(调用了析构函数)。这让我百思不得其解,我只是传递了一个引用而已啊,为什么会发生析构呢?经过调试发现在调用deal函数的时候发生了pair的拷贝操作,由于A类的拷贝构造是共享资源,所以在deal函数的参数pr析构的时候释放了资源。
那么问题就变成了为什么将mp的元素pr传递给deal就会发生拷贝?我们知道C++中普通引用要求两者的类型必须一致,而常量引用却可以发生类型转换,莫非是因为形参和实参的类型不一致?由于range循环的元素pr是推断出来的,那么的确有可能出现这种情况。接下来我们的问题就是搞清楚auto &pr是什么类型,然后修改deal的形参类型即可。(当然也可以将deal变成模板成员函数,然后用万能引用也可以解决问题)。
《Effective Morden C++》的条款4向我们介绍了如何查看型别推导的结果,有三种方法,分别是依赖IDE、依赖编译器诊断信息和在运行时输出。我使用的是Clion进行开发,还是很靠谱地显示了pr的类型为:std::pair&,而我们在类B中声明的形参为const std::pair&,怪不得发生了拷贝构造。 于是我们修改B中的形参就可以啦。
如果IDE没有这么智能,那么还是可以依赖我们的好兄弟编译器的,《Effective Morden C++》中介绍了一种很trick的方法就是使用一个没有定义的模板类或者模板函数,只要我们试图使用这个模板,就会诱发一个错误信息,而编译器肯定会在错误信息中加上类型的名字。
于是我写了一个简单的测试函数:

template
void printType(T t);

经过运行,编译器发出了错误警告:

undefined reference to `void edward::printType >(std::pair)’

我也尝试了第三种看起来最优雅的运行时输出,书中喷了一下标准库的typeid的实现,推荐使用boost库中的boost::typeindex::type_id_with_cvr().pretty_name()进行输出。但是我可能没有正确安装好boost库,导致找到这个函数。

总之,我们要千万小心map和unordered_map的元素类型为std::pair,如果忘记const可能会不小心产生拷贝操作,不仅仅会带来性能损耗,而且可能会产生RuntimeError。

暑期编程PK赛 得CSDN机械键盘等精美礼品!
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1015112.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号