C++自我学习.5
1.数据结构(data structure)
1.vector 的初始化:
(1)vector<int> a(10)定义了10个整型元素的向量(尖括号中为元素类型名,它可以是任何合法的数据类型),但没有给出初值,其值是不确定的
(2)vector<int> a(10,1)定义了10个整型元素的向量,且给出每个元素的初值为1
(3)vector<int> a(b)用b向量来创建a向量,整体复制性赋值
(4)vector<int> a(b.begin(),b.begin()+3)定义了a值为b中第0个到第2个(共3个)元素,b为向量
(5)vector<int>a (b,b+7) int b[7]={1,2,3,4,5,9,8};从数组b取值
(6)vector<int>={ }列表初始化
2.数组传参
array
void maopao_paixu ( array<int ,10> b) 值传递
void maopao_paixu (array<int,10>&b) 引用传递
内置数组
void mao_paixu (int b[],int arraysize ) 引用传递
vector
void print(vector<stud>student) 值传递
print(student) 主调函数写个向量名就行
3.vector成员函数
1.assign(4,2)初始化元素个数4,值2
2.begin() 返回容器中第一个元素
3. end() 返回容器最后一个元素
4. rbegin()返回最后一个元素的访问迭代器(地址)
5. rend() 返回第一个元素之前一个位置的访问迭代器(地址)
6. size()返回容器中元素的数量
7. nmax_size()返回容器可容纳元素的最大数量,其值始终等于初始化 array 类的第二 个模板参数 N
8. empty() 判断容器是否为空,空true,非false
9. front()返回容器中第一个元素
10. back() 返回最后一个元素
11. data()返回一个指向容器首个元素的指针。利用该指针,可实现复制容器中所有元素等类似功能
12. fill(x)将 x 这个值赋值给容器中的每个元素,相当于初始化
array1. swap(array2)交换 array1 和 array2 容器中的所有元素,但前提是它们具有相同的长度和类型
- clear( )清空元素
- pop_back( )删除最后一个元素
- push_back( )从最后添加一个元素
- erase(a.begin()+1,a.begin()+3)删除a[1],a[2],不包括a[3]
- insert(a.beign()+1,3,5)从a[1]开始插入3个数,值为5
insert(a.begin()+1,b+3,b+6)从a[1]开始插入b[3],b[4],b[5]
18.swap(b)a,b元素整体交换
4.vector关系比较
相等则返回true,否返回false
特性:
1.array,vector都支持通过at函数进行越界检查,不是通过 [ 下标 ]
2.array除了有元素空间,还有长度空间
3.vector相较于array,内置数组是不定长的,随时添加新元素
4.array,vevtor,内置数组都支持下标遍历,内置数组不基于范围的元素遍历(因为不知道自己的大小)
- 异常捕获
try....catch语句
try中包含可能抛出异常的代码,catch中包含处理异常的代码
附:
不同类型的try可由相应的catch来一一对应和处理
at()函数,提供边界检查和抛出异常功能,实参是下标
如果下边有效,则返回该元素
如果下标无效,则抛出异常out_of_range(在头文件stdexcept>)
catch中接受引用的异常形参ex,调用成员函数what()存储错误消息,结束异常处理
指针
1.指针指向一个变量的内存地址,它本身也是一个存储空间。只不过存储的是一个变量的地址而已。真正理解间接引用
注意:指针本身是个整型,4个字节来存储地址,不过却可以指向任何的数据类型,就是说存储任意数据类型的地址,指针最好先初始化为0,sizeof(指针)==4
例:
int *a=0;
char *b=0;
cout<<a; 输出:00000000000...
cout<<b 输出:0000000....
地址运算符 &
注意:
引用变量的&总是跟在一个类型名后面,
Int &a=x; //声明一个引用时,&是其类型的一部分
补:
*间接操作符,解引用
++前置,后置优先级都在在*前
2.*aptr和aptr的不同意义
1.*aptr返回指针指向的对象的值,*aptr上的任何操作都相当于在y上,如同y的别名
2.aptr就是一个存储地址的变量
3.指针的算术运算(只能应用在存储内置数组元素地址的指针)
例1:
int a[5];
int *aptr=a;
aptr++,aptr--,aptr+3,aptr-4
具体原理:原地址+n*数据类型的字节大小
注意:
无法对数组名a进行算术运算
例2:指针相减
x=aptr-bptr,返回元素个数
4.指针与内置数组(重要):
普通指针偏移量表示法,内置数组名指针偏移量表示法
int *aptr=a;
1.*(aptr+3);注意带了*号,就是元素值,返回a[3]
2.*(a+3);也是返回a[3]
3.aptr[3],注意只有这种形式,才有不带*号,也返回值元素
4.int a[],a+i , *p
a+i(得到地址) 就是 &a[i]
p=a+i 等价于 p=&a[i]
关键:字符指针与字符数组
注意:
1.sizeof( )获得的字节数包含空字符\0,strlen()获取字符串长度不包栝‘\0’
2.赋值,字符指针可以随意用字符串赋值,字符数组不行,只能挨个元素,一个位子用一个字符赋值,除非用strcpy()
3,对字符指针无法输入,因为赋给字符指针的字符串存在常量区,无法更改
补:
C字符串操作函数(内置数组) <cstring>
复制
char*strcpy(char *s1,const char*s2) 既然是指针,实参一定是地址,记住了,记住
char*strncpy(char *s1,const char*s2,n)
例:
const char *p=”abcd”;
char str[50]=”sdf”
strcpy(str+2,p+2) 从p+2这个地址开始的串拷给str+2这个地址后面的串空间
cout<<str
strcpy(p+2,str+2)
cout<<p 报错,无法修改常量空间的字符串,只能读
追加
char*strcat(char *s1,const char*s2)
char*strncat(char *s1,const char*s2,n)
比较
char*strcmp(const char *s1,const char*s2)
char*strcmp(const char *s1,const char*s2,size_t n)
分割
char*strtok(char *s1,const char*s2)
char*strtok(NULL,const char*s2)
个数
size_t strlen(const char*s)
返回空字符前的字符个数
注意:
char c[]={‘a’ , ‘b’ , ’d’ }
abd结尾没有空字符,空字符不知道在哪
strlen结果就不可知
当然sizeof(c)还是3个字节
6.指针传参,指针二次传参
核心:
1.实参一定是地址
2.指针会改变实参的值
7.const修饰指针(权限)
1.指向非const数据的非const指针 int*ptr =&y
可以再指向其他数据
可以修改指向的数据
2.指向const数据的非const指针 const int*ptr =&y
可以再指向其他数据
不可以修改指向的const数据
3.指向非const数据的const指针 int *const ptr =&y
不可以再指向其他数据,始终指向同一片内存
可以修改指向的数据
4.指向const数据的const指针 const int*const ptr=&y
不可以再指向其他数据,始终指向同一片内存
不可以修改指向的const数据
补:
sizeof ( )运算符
获取变量所占的内存总字节大小
6.通用指针void*(可以表示任何指针类型)
合法运算
1.向void*赋值地址
例:
void *a=nullptr
int x=0
int *b=&x
a=b
2.强制转换后,void*才能给变量赋值
int *a=nullptr;
void*b=nullptr
a=(int *)b
3.void*可以直接和其他类型指针比较存放的地址
int *a=nullptr;
void*b=nullptr
cout<<(a==b)
非法运算:
void*只有对其强转后,才能像正常指针一样操作(编译器必须知道指针特定的类型,才能确定该指针间接引用的字节数)
double a=3.14;
void*a=&a;
cout<<*(double*)void 输出3.14
补;
void*指针作为返回值和形参
注意:
不能返回局部变量指针,出了函数就会消失,无法访问,会返回野指针
cin指的是输入端是键盘,对象>>.输入端是对象,
>>代表数据流动的方向
arr、arr[0]、&arr[0]和&arr区别
- arr:数组名,同时也表示数组第一个元素的首字节地址,是一个常量值。
- arr[0]:数组一个元素,可以进行读写操作。
- &arr[0]:等价于arr,是一个地址常量,只能作为右值。
- &arr:数组首地址,其值与arr相等,但含义完全不同。&arr,是将整个数组作为一个新的数组类型,&arr就是这个类型对应内存空间的首地址。
vector动态数组
可以后加元素
如vector<int>insert(7);
insert.push_back(1000);
//那么将1000作为vector对象insert的第8个元素。
抛出异常,解决异常
try//如果代码正常运行,则可视为普通代码,则会忽略对应接收异常的代码catch;但如果抛出异常,就会很有用,在不打扰程序正常运行的情况下,让程序看似没有异常。
例:下标越界的异常
cout<<"attempt to display insert. at (15) ";
cout<<insert.at(15);
//at()成员函数提供边界检查和抛出异常功能,就此例而言,抛出一个out_of_range异常(在头文件stdexcept)
}
catch( out_of_range &ex) //接收引用的异常形参ex
{
cerr<<" "<<ex.what(); //标准错误流
}
int *p
1.*p++ 先拿值,再移动指针
2.(*P)++ 拿值,给值+1
3.*(p++) 先拿值,在移动指针
cout<< <<自带一层解引用