顺序容器:顺序容器的操作


一、容器元素都是副本

在容器中添加元素时,系统是将元素值复制到容器里。类似地,使用一段元素初始化新容器时,新容器存放的是原始元素的副本。

被复制的原始值与新容器中的元素各不相关,此后,容器内元素值发生变化时,被复制的原值不会受到影响,反之亦然。

void test_copy()
{
	int i = 10;

	std::vector<int> vec;
	vec.push_back(i);

	*(vec.begin()) = 9;
	std::cout << *(vec.begin()) << std::endl;	//9
	std::cout << i << std::endl;			//10,放进容器的值是副本,对容器的元素进行修改不影响原来的对象
}

二、任何对容器的增删操作都可能对已经定义的迭代器失效

void test_iterator()
{
	std::list<int> ls;
	ls.push_front(1);

	std::list<int>::iterator begin = ls.begin();
	std::cout << *begin << std::endl;	//1

	ls.push_front(2);	// 对于push_front操作只适合list和deque容器
	std::cout << *begin << std::endl;	//1,begin依然指向原来的元素,并没有指向新添加的元素2

	begin = ls.begin();	//
	std::cout << *begin << std::endl;	//2
}

三、测试insert操作

void printDeque( std::deque<int>::iterator &begin, std::deque<int>::iterator &end )
{
	while( begin != end )
	{
		std::cout << *begin << "_";
		++begin;
	}
	std::cout << std::endl;
}

// 测试insert操作
void test_insert()
{
	std::deque<int> de;
	for( unsigned int index = 0; index != 5; ++index )
	{
		de.push_front(index);
	}

	// 逆序迭代器
	std::deque<int>::reverse_iterator rit = de.rbegin(); // 指向容器的最后一位
	while( rit != de.rend() )	// 容器第一位的前一位
	{
		std::cout << *rit << std::endl;
		++rit;
	}

	std::deque<int>::iterator it;
	it = de.begin();
	++it;

	// 在指定的迭代器前面插入对象的副本
	de.insert(it,10);
	std::deque<int>::iterator begin = de.begin(), end = de.end();
	printDeque(begin, end);	// 4_10_3_2_1_0_

	// 在指定的迭代器前面连续插入n个对象的副本
	de.insert(it,3,20);
	std::deque<int>::iterator begin2 = de.begin(), end2 = de.end();
	printDeque(begin2,end2);// 4_10_20_20_20_3_2_1_0_

}

// 插入两个迭代器标记范围内的元素
void test_insert_2()
{
	std::deque<int> de;
	for( unsigned int index = 0; index != 5; ++index )
	{
		de.push_front(index);
	}

	int arr[] = { 10, 11, 12, 13, 14, 15};
	de.insert(de.begin(), arr, arr+sizeof(arr)/sizeof(int)/2);
	std::deque<int>::iterator begin = de.begin(), end = de.end();
	printDeque(begin, end);	// 10_11_12_4_3_2_1_0_
}


int main()
{
	test_insert_2();
	return 0;
}

四、放进容器的是对象的副本,取出容器的是对象的引用

// 从容器中返回引用的方法:front()、back()、begin()、end()、at【只对vec和deque有效】等
void test_inout()
{
	int i = 10;

	std::vector<int> vec;
	vec.push_back(i);

	i = 100;

	std::cout << i << std::endl;			// 100
	std::cout << vec.front() << std::endl;	// 10,修改i的值并没有改变容器中的副本

	// 返回的是引用,修改j的值等同于修改容器中对象,如果将j定义为:int j = vec.front(),
	// 则对j的修改不会对容器的对象起作用
	int &j = vec.front();
	j = 1000;
	std::cout << i << std::endl;			// 100
	std::cout << j << std::endl;			// 1000
	std::cout << vec.front() << std::endl;	// 1000,
}

五、关于resize操作

resize 操作可能会使迭代器失效。在 vector 或 deque 容器上做 resize 操作有可能会使其所有的迭代器都失效。
对于所有的容器类型,如果 resize 操作压缩了容器,则指向已删除的元素迭代器失效。

/*
c.resize(n):
	调整容器 c 的长度大小,使其能容纳 n 个元素,如果 n < c.size(),则删除多出来的元素;否则,添加采用值初始化的新元素
c.resize(n,t):
	调整容器 c 的长度大小,使其能容纳 n 个元素。所有新添加的元素值都为 t
*/
void test_size_resize()
{
	std::vector<std::string> vec;
	if(vec.empty())
	{
		std::cout << vec.size() << std::endl;
	}
	std::cout << "容器能容纳的最多元素个数为:" << vec.max_size() << std::endl;	// 1073741823

	vec.push_back("111");
	std::cout << vec.size() << std::endl;	// 1
	vec.resize(10);
	std::cout << "resize(10): " << vec.size() << std::endl;	// 10

	vec.resize(3, "aaa");
	std::cout << "resize(3): " << vec.size() << std::endl;	// 3
	for( unsigned int i = 0; i != vec.size(); ++i )
	{
		// 0:111  1:  2:
		// resize(n,t):只有n大于原来的容器的容量时,新添加的元素才会初始化为t
		// 否则调用就调用resize(n)方法
		std::cout << i << ":" << vec[i] << std::endl;
	}

	vec.push_back("222");
	vec.push_back("333");
	std::cout << vec.size() << std::endl;	// 4
}

六、begin/end/front/back/at

// 如果容器为空或容器的大小为1,则front和back操作返回的对象相等
void test_front_back()
{
	std::list<int> ls;
	int front = ls.front(), back = ls.back();
	if( front == back )
	{
		// 调用空容器的 front 或 back 函数,通常都会导致程序出现严重的错误
		std::cout << "front element equals back element" << std::endl;	// ok
	}

	ls.push_back(1);
	front = ls.front();
	back = ls.back();
	if( front == back )
	{
		std::cout << "front element equals back element" << std::endl;	// ok
	}
}

/*
 在这段程序中,有两个地方值得注意:
	1、end 迭代器指向容器的超出末端的下一位置,因此必须先对其减 1 才能获取最后一个元素;
	2、在调用 front 或 back 函数之前,或者在对 begin 或end 返回的迭代器进行解引用运算之前,必须保证ls容器非空,
	如果该list 容器为空,则 if 语句内所有的操作都没有定义。
*/
void test_front_back_begin_end( std::list<int> &ls )
{
	if( !ls.empty() )
	{
		std::list<int>::reference begin = *ls.begin();
		std::list<int>::reference front = ls.front();

		if( begin == front )
		{
			std::cout << "ok" << std::endl;	// ok
		}

		std::list<int>::reference end = *--ls.end();
		std::list<int>::reference back = ls.back();
		if( end == back )
		{
			std::cout << "ok" << std::endl;	// ok
		}
	}
}

// 使用下标操作的两种方式仅只适合vector和deque,并不适合list
// 但是如果给出的下标无效,at 函数将会抛出 out_of_range异常
void test_at()
{
	std::vector<std::string> svec;
	std::cout << svec[0];
	std::cout << svec.at(0);
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值