学习笔记(六十一)vector、array和数组

C++语言 码拜 9年前 (2015-11-26) 1307次浏览
假如有不对的地方,请指正,非常感谢。
模板类vector
模板类vector相似string类,是一种动态数组
例如说,string类可以将一个string的字符串插入到另外一个string类字符串后面。vector也可以有相似的功能。
而对于vector类来说,他是一个数组,例如我们数组中有第一个A和第二个元素B,然后我们可以把C插入在A和B之间,这个时候,数组第一个成员为A,第二个为C,第三个为B。
我们还可以把其中一个成员删掉,这样,后面两个成员自动向前进一位,例如删掉第一个成员A,于是第一个成员变成了C,第二个成员变成了B。
头文件:

#include<vector>	//使用vector类需要引用头文件vector

创建vector类数组
vector<类型名>数组名(成员个数);
例如:

vector<double>vd(n);

注意:成员个数可以为变量,这样在使用的时候更自由。
给vector数组成员赋值:
可以像使用普通数组一样,使用 变量名[编号] 来进行赋值,注意:第一个成员的编号为0,和数组是一样的。例如:

vd[1] = 22;

数组vd的第二个成员的值为22。
注意:vector类不能在声明的时候,同时进行初始化为数组成员赋值。
在vector类的数组中插入一个成员:
使用命令 数组名.insert(数组名.begin()+插入位置,插入的成员);
例如,给vd数组的第二个位置插入一个成员,成员的值为a(a可以是变量名,也可以是常量,但需要已经初始化)。如代码:

vd.insert(vd.begin()+1, a);

注意:插入到第二个位置,是+1,而原来数组第二个位置的成员,将依次向后退一位,例如原来第二个位置的成员,在插入后就在第三个位置了。
删除vector类数组中的一个成员:
使用命令 数组名.erase(数组名.begin()+删除位置):
例如,删除vd数组第一个成员,那么删除位置就应该写0。注意,数组第一个位置的编号是0。如代码:

vd.erase(vd.begin() + 0);

在vector类数组的尾部插入一个成员:
即在数组的最后插入一个成员,这个成员的插入,增加了数组成员的个数。代码为:  数组名.push_back(数组成员);
例如在数组最后加入成员10,代码:

vd.push_back(10);

vector类数组的成员数:
数组成员数是可以变的,用 数组名.size() 可以显示成员的数量。——按照某个帖子的说法是 向量大小 。
①在创建并声明时,成员数为声明时的成员数,即使某个成员并没有被赋值,也会被算入在内。
②在插入成员,无论是在中间插入或是在尾部插入,都会增加成员数。
③在删除成员时,也会相应减少成员数。
代码是:

cout << "vd数组的宽度为:" << vd.size() << endl << endl;	//显示数组的成员数

将一个vector数组赋值给另外一个vector数组:
当两个数组类型相同,(元素数无需相同),可以进行赋值。
格式为:

目标数组名=源数组名;

上代码:

#include<iostream>
#include<vector>	//使用vector类需要引用头文件vector
int main()
{
	using namespace std;
	int n;	//声明变量n
	cout << "输入vector类的数组元素个数(请大于等于3):" << endl;
	cin >> n;	//要求用户输入变量n
	vector<double>vd(n);	//创建一个double类型的vector动态数组,数组元素为n个,数组名为vd
							//即 vector<类型名>数组名(成员数量),注意,成员数量可以为变量
	cout << "输入vd[0]:";
	cin >> vd[0];	//调用的时候,用vector类的数组名加元素编号,第一个元素编号为0,同数组。要求用户输入vd[0]的值
	cout << "将vd[1]赋值22。" << endl;
	vd[1] = 22;	//给vd[1],即数组中第2个成员,赋值22
	cout << "vd[0]为" << vd[0] << "。vd[1]为" << vd[1] << endl;
	cout << "vd数组的宽度为:" << vd.size() << endl << endl;	//显示数组的成员数
	int a = 1;
	vd.insert(vd.begin() + 1, a);	//在数组中第二个位置插入变量a
	cout << "现在,创建常量a=1,然后将a插入在vd[1]之前,即把a插入到vd[1]的位置,原来的vd[1]依次顺延到下一位。" << endl;
	cout << "vd[0]为" << vd[0] << "。vd[1]为" << vd[1];
	cout << "vd[2]为:" << vd[2] << endl;	//原本第二个位置的成员被顺延到第三个位置了
	cout << "vd数组的宽度为:" << vd.size() << endl << endl;	//显示数组的成员数
	vd.erase(vd.begin() + 0);	//删除数组中第一个成员,其他成员依次向前进一位
	cout << "现在,删除vd[0]当前成员,原来的vd[1]就变成vd[0]了。" << endl;
	cout << "vd[0]为" << vd[0] << "。vd[1]为" << vd[1] << endl;
	cout << "vd数组的宽度为:" << vd.size() << endl << endl;	//显示数组的成员数
														//n = 5;	//虽然上面vd[n]声明了数组的成员数,但单纯更改变量n,其实是不能改变vd数组的成员个数的。
	int b = 2, c = 3, d = 4;	//声明新的变量bcd并初始化
	vd.insert(vd.begin() + 2, b);	//在第三个位置插入成员b
	vd.insert(vd.begin() + 3, c);	//在第四个位置插入成员c
	vd.insert(vd.begin() + 4, d);	//在第五个位置插入成员d
	cout << "从第三个位置依次插入b=2,c=3,d=4" << endl;
	cout << "目前,vd[0]为" << vd[0] << "。vd[1]为" << vd[1] << "。vd[2]为" << vd[2] << "。vd[3]为" << vd[3] << "。vd[4]为" << vd[4] << endl;
	cout << "vd数组的宽度为:" << vd.size() << endl << endl;	//显示数组的成员数
														//vd.erase(vd.begin() + 1, vd.end() + 2);
														//按照说法,这行代码可以删除多个数组成员,但实际测试中却出错了。
	vd.push_back(10);	//在数组的最后插入成员,值为10
	cout << "在vd数组的尾部插入常量10。" << endl;
	cout << "第" << n + 4 << "个元素是数组的最后一个元素,vd[" << n + 3 << "]的值为:" << vd[n + 3] << endl;	//注意,这行是可以通过变量来显示相应的数组的成员的,例如vd[n+3]是数组第n+4个成员
	cout << "vd数组的宽度为:" << vd.size() << endl << endl;	//显示数组的成员数
	vector<double>bb(20);	//创建vector类数组bb,原因是要将vd数组赋值给bb数组,因此成员数不重要
	bb = vd;	//将vd数组赋值给bb数组,二者将完全等同
	cout << "将vd数组赋值给bb数组\n";
	cout << "bb数组第四个成员bb[3]=" << bb[3] << endl;
	cout << "bb数组的成员数为:" << bb.size() << endl;
	system("pause");
	return 0;
}

输出:

输入vector类的数组元素个数(请大于等于3):
33
输入vd[0]:55
将vd[1]赋值22。
vd[0]为55。vd[1]为22
vd数组的宽度为:33
现在,创建常量a=1,然后将a插入在vd[1]之前,即把a插入到vd[1]的位置,原来的vd[1]依
次顺延到下一位。
vd[0]为55。vd[1]为1vd[2]为:22
vd数组的宽度为:34
现在,删除vd[0]当前成员,原来的vd[1]就变成vd[0]了。
vd[0]为1。vd[1]为22
vd数组的宽度为:33
从第三个位置依次插入b=2,c=3,d=4
目前,vd[0]为1。vd[1]为22。vd[2]为2。vd[3]为3。vd[4]为4
vd数组的宽度为:36
在vd数组的尾部插入常量10。
第37个元素是数组的最后一个元素,vd[36]的值为:10
vd数组的宽度为:37
将vd数组赋值给bb数组
bb数组第四个成员bb[3]=3
bb数组的成员数为:37
请按任意键继续. . .

模板类array(限C++11):
vector类比数组强大,但是代价是效率较低(不知道为什么,原因是使用的是动态存储区么?),假如是长度固定的数组(原因是vector是动态数组,可以增加成员或减少成员),使用数组更高,但代价是不那么安全和方便(不方便本人知道,但是不安全是为什么?)。
因此,c++11增加了模板类array,使用的是栈(静态存储区)(vector是堆,动态存储区),位于名称空间std之中。
因此array效率和数组相同,但是更安全和方便,要创建array对象,需要包含头文件array。array对象的创建和语法与vector稍有不同。
头文件:

#include <array>	//使用模板array需要调用头文件array

声明和创建:
声明一个array类数组和vector数组方式不同,格式为: array<类型名,成员数常量>数组名;
例如创建一个int类型,成员数为3,数组名为a的array类的代码为:

array<int, 3> a;

注意:①vector的成员数是可变的,而array的成员数是固定的。
②vector和array都是<>括号,而不是小括号()。
初始化和赋值:
原因是和数组相似,所以初始化和赋值的方式相似数组。
初始化的格式为: array<类型名,成员数>数组名={成员1,成员2,……};
赋值格式为: 数组名[编号]=常量;
例如,初始化数组a的前2个成员的代码为:

array<int, 3> a = { 1,2 };

给a的第三个成员赋值的代码为:

a[2] = 4;

显示成员数:
与vector类相同,显示成员数的代码为: 数组名.size()
例如代码:

cout << a.size() << endl;

上代码:

#include<iostream>
#include<array>	//使用模板array需要调用头文件array
int main()
{
	using namespace std;
	array<int, 5> a = { 1,2 };	//创建array类数组a,成员数为5,类型为int类,并为前2个成员赋值
	a[2] = 4;	//为第三个成员赋值
	cout << a[0] << endl;	//显示第一个成员的值
	cout << "请为数组第四个成员赋值:" << endl;
	cin >> a[3];	//读取用户输入,为第四个成员赋值
	cout << "第四个成员的值为" << a[3] << endl;		//显示第四个成员的值
	cout << "数组的成员数为:" << a.size() << endl;	//显示成员数

	array<int, 5 >b;	//创建数组b
	b = a;	//由于数组和数组a的类型相同,成员数相同,故可以将数组a赋值给数组b
	cout << "array类数组b等于数组a,b的第二个元素为b[1]=" << b[1] << endl;	//显示数组b第2个元素,和数组a第二个元素相同
	system("pause");
	return 0;
}

输出:

1
请为数组第四个成员赋值:
55
第四个成员的值为55
数组的成员数为:5
array类数组b等于数组a,b的第二个元素为b[1]=2
请按任意键继续. . .

vector对象、array对象和普通数组之间的相同和差异:
学习笔记(六十一)vector、array和数组

解决方案:20分
vector 也可以初始化啊;
std::vector<double> x(5, 2,45); // 5 个元素,全部初始化为 2.45.
std::vector<double> x = {1.0, 1.1, 1.2, 1.3};
std::vector<double> x{1.0, 1.1, 1.2, 1.3};
后两个需要 C++11.
解决方案:5分
vector 在末尾插入或删除数据效率很好,但在前面插入与删除元素效率较低,原因是要移动后面的元素
解决方案:5分
内存区域占用,可分两种情况考虑
一种是对象本身,占用的内存
一种是 持有handle (指针,有时候引用也可)的对象,handle 指向的内存区域
例如 string
sizeof(stirng)
是对象 string 占有的内存,是固定大小
string 的内容,需要占用动态区
string::size() 是内部各个字符占用的内存大小,
是必须保证的大小,通常会占用比这个大小多一点的内存。
解决方案:10分
string* p= new string(“1234567891011121314.。”);
这里 指针p可以在静态区,栈区 这两个数据区域的任何一个地方。
主要看怎么样定义指针 p,定义在何处
new 的这个string对象在堆区,大小为 sizeof(string) 这个对象通常并不包含它的数据 “1234567891011121314.。”
它的数据 “1234567891011121314.。” 一般存放在堆区的另一块内存中
你还可以 这么做
struct XXX {
string *p;
};
定义一个 XXX 对象 x,
XXX x;
或new 一个XXX对象
px=new XXX;
然后,再初始化他的指针成员 p;….

这个持有者例如px,p,是必须存在的,
原因是高级语言,是按照名字,安排变量的存储空间的,按照名字编译代码的。
甚至汇编语言,也需要名字处理变量。
而动态分配的对象,并没有名字。
至少从程序员的角度,看不到他的名字。

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明学习笔记(六十一)vector、array和数组
喜欢 (0)
[1034331897@qq.com]
分享 (0)