Effective STL 中文版记录(四)

Effective STL 章节(四)

——50条有效使用STL的经验(25/50)
关联容器专项



第十九条、理解相等(equality)和等价(equivalence)的区别

直接举例:

test1 == test2 // 相等
!(test1 < test2) && !(test2 < test1) // 等价

这一条的意义是提示你,在使用非关联容器时,请使用他们自带的比较函数,而不是直接==判断

因为他们是用“等价”来作为两个元素是否相同的判据的

第二十条、为包含指针的关联容器指定比较类型

考虑如下代码

std::set<std::string*> datas;
datas.insert(new std::string("Anteater"));
datas.insert(new std::string("Wombat"));
datas.insert(new std::string("Lemur"));
datas.insert(new std::string("Penguin"));

再输出这些元素,大概率是没法输出正确字符的

问题就出在set储存这个指针时,需要进行比较,调用了一个比较函数,这个函数是不合适的

因为存的是指针,所以set在排序时使用的是std::string*的大小顺序,而不是std::string代表的字符

解决方法就是自己构建一个比较函数,用std::sting比较,而不是指针,并传给set

auto func = [](const string * p1, const string * p2)
{ 
	return *p1 < *p2; 
}
set<string *, func> datas;
...  // do something

也就是说,当容器保存的是指针时,请注意要为它指定比较类型

第二十一条、总是让比较函数在等值情况下返回false

细节不用太了解,只需要知道在定义比较函数时遵守:

bool func(T a, T b)
{
	return a < b;
	// return a > b;
}

能看到,如果a=b,不管怎么样都是false,这是为了保护标准关联容器

比如set中已经有了10,再次插入10,使用a<=b判断会怎么样

!(10 <= 10) && !(10 <= 10)
!(true) && !(true)
false && false
false

也就是说,这个10和set中的10是不一样的,那么就会导致set有两个10,那么set也就不是set了

第二十二条、切勿直接修改set或multiset中的键

set和multiset会按照元素的键值对元素排序,如果修改了键值,那么排序是否依然正确就没法保证了

所以不要直接改它的键值

如果必须修改这个元素的键值,怎么办?

对其拷贝,再拷贝上修改,再插入拷贝,同时删除原本的元素

auto i = set.find("a");
if(i != set.end())
{
	AClass temp(*i);  // 拷贝原本的元素
	temp.setKey("b"); // 在拷贝中修改
	set.erase(i ++);  // 先删除原本的元素,并且递增迭代器,保证有效性
	set.insert(temp); // 插入拷贝
}

总之不能在set里面直接改元素键值

第二十三条、考虑用排序的vector替代关联容器

在需要搜索工作的环境中,有时候排序的vector容器搜索比关联容器更快

假设有巨大的数据量,vector能够保证内存连续,而关联容器则会把内存散落各地

这就可能导致vector的搜索反而比关联容器快(具体可以搜C++内存对齐问题)

但是!仅在你知道使用环境中,查找工作和插入删除工作几乎不在一起时,才适合

不然vector的插入删除和重排序在这里是毫无好处的

第二十四条、当效率至关重要时,请在map::operator[]与map::insert之间做出谨慎选择

在map的使用中有:

map<int, int> m;
m[1] = 5;

这个意思是,将元素5插入map中键值为1的位置,如果已经有了该元素,就更新为5,如果没有,就插入

在插入时,它实际上是调用了三个函数:构造{int, int}、插入、赋值

这样明显不如直接调用insert函数来的快,省去析构函数和赋值函数的调用

但是在更新时,则是反过来的,所以

当对map进行插入时,请使用insert函数
当对map进行更新时,请使用[]赋值

第二十五条、熟悉非标准的散列容器

散列容器指的是以哈希表为基础的容器,这本书比较老了,现在C++11往后已经有了散列容器

如unordered_set unordered_map等,在从零开始手写STL库中也有实现

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值