C++标准库进阶4

十六、map的operator[]和insert

map对象添加元素的方法有两种,一种是使用operator[],另一种是使用insert方法,那么这两种方法的区别在哪?

1、当向map对象中添加一个新的键值对时,请使用insert方法

示例

class test
{
public:
	test() {cout<<__func__<<endl;}
	test(int val) {cout<<"test(int val)"<<endl;}
	test(const test &t) {cout<<"test(const test &t)"<<endl;}
	test &operator=(const test &t) {cout<<__func__<<endl;return *this;}
	~test() {cout<<__func__<<endl;}
};

int main(int argc, char const *argv[])
{
	map<int, test> tm;
	tm[1]=10;
	cout<<"--------"<<endl;
	tm.insert(make_pair(2,20));
	cout<<"--------"<<endl;
	return 0;
}

tm[1]=10;的执行过程如下:首先将10隐式转化为一个临时的test对象,调用构造函数test(int val),因为tm[1]没有对应任何value,所以临时创建一个test对象,调用了构造函数test(),之后,调用operator=进行赋值操作,最后隐式转化的临时对象被释放,调用析构函数

而tm.insert(make_pair(2,20));仅仅是将20隐式转化为一个临时的test对象,调用构造函数test(int val),除此之外没有其他操作

所以,当向map对象中添加一个新的键值对时,insert方法比operator[]要少执行三个操作,所以insert方法效率较高

 

2、当更新map对象中已存在的键对应的值时,请使用operator[]方法

示例

int main(int argc, char const *argv[])
{
	map<int, test> tm;
	tm[1]=10;
	cout<<"--------"<<endl;
	tm.insert(make_pair(1,20)).first->second=30;
	cout<<"--------"<<endl;
	tm[1]=30;
	cout<<"--------"<<endl;

	return 0;
}

tm.insert(make_pair(1,20)).first->second=30;的执行过程如下:首先30和make_pair中的20隐式转化为test对象,调用了两次test的构造函数,因为map对象中原来有key为1的键,所以插入失败,20对应的临时对象调用了一次析构函数,返回的pair对象中的迭代器指向key为1的键值对,接着调用operator=进行赋值操作,赋值操作后,30对应的临时对象被析构,整体之行结束

而tm[1]=30;仅仅比没有上个示例中少调用了一个test()构造函数

所以,当对map中的键值对更新时,operator[]比insert操作少执行了一次构造函数和一次析构函数,所以此时operator[]效率更高

 

十七、迭代器和迭代器适配器

https://blog.csdn.net/Master_Cui/article/details/108512730

https://blog.csdn.net/Master_Cui/article/details/108566447

 

十八、如果所使用的算法需要指定一个目标区间,那么必须确保目标区间足够大

如果使用的算法需要指定一个目标区间,那么必须确保目标区间足够大,或者确保它会随着算法的运行而增大。要在算法执行过程中增大目标区间,请使用插入型迭代器

示例

int add(int para) {para+=10;return para;}
void print(int para){cout<<para<<endl;}
int main(int argc, char const *argv[])
{
	vector<int> v={1,2,3,4,5};
	vector<int> res;
	res.reserve(100);
	transform(v.begin(), v.end(), res, add);
	for_each(res.begin(), res.end(), print);
	return 0;
}

出现该错误的原因就是在插入的位置之后,没有足够的内存空间容纳插入的元素。transform本身不会让res空间扩大,而res本身为空,res.begin()后没有足够的内存空间,所以在运行时出现了段错误

解决办法有两个:

1、对res进行resize操作,保证res中有足够大的空间容纳新添加的元素

int add(int para) {para+=10;return para;}
void print(int para){cout<<para<<endl;}
int main(int argc, char const *argv[])
{
	vector<int> v={1,2,3,4,5};
	vector<int> res;
      res.reserve(10);
	res.resize(10);
	transform(v.begin(), v.end(), res.begin(), add);
	for_each(res.begin(), res.end(), print);
	return 0;
}

 

2、对res使用插入迭代器,确保在插入的过程中,res的空间能随着插入的过程不断变大

int add(int para) {para+=10;return para;}
void print(int para){cout<<para<<endl;}
int main(int argc, char const *argv[])
{
	vector<int> v={1,2,3,4,5};
	vector<int> res;
	res.reserve(100);
	transform(v.begin(), v.end(), back_inserter(res), add);
	for_each(res.begin(), res.end(), print);
	return 0;
}

上述示例中,使用reserve可以让容器再添加元素的过程中不用重新分配内存,提高效率

 

参考

《Effective STL》

 

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值