C++学习笔记(重温计划之五)

3、数据类型(下)

 1)向量(Vectors)

   Vector是C++标准模板类库的重要组成部分,使用时需要包含头文件vector.主要定义方式如下:

    vector <int> a(10);                     //定义了10个整数元素,但没有赋初值

    vector <int> b(10,1);                  //定义了10个整数元素,且每个元素的初值为1

    vector <int> c(b);                       //用一个现成的向量创建一个向量

    vector <int> d(b.begin(),b.begin()+3);             //定义了一个其值为向量b前3个值的向量

 我们知道,当输出一个数组时我们一般用循环实现.在vector中,有相应的遍历器函数,形式为vector<int>::iterator,例如:

   for(vector<int>::iterator it = a.begin(); it != a.end() ; ++it)

    cout <<*it <<“ ”;

   有关向量的其他操作如下:

a.assign(b.begin(),b.begin()+3);     //将b的0-2元素构成的向量赋给a a.assign(4,2);                       //将a向量只含0-3元素,且赋为值2 int x = a.back();                    //将a的最后一个向量元素值赋给整数变量x a.clear();                           //a向量元素清空 if(a.empty()) cout << “empty”;       //a.empty()作为条件判断空或非空 int y = a.front();                   //将a的第一个向量元素赋给整数变量 ya.pop_back;                         //删除a向量的最后一个元素 a.push_back(5);                      //在a向量最后插入一个元素,其值为5 a.resize(10);                        //将向量元素个数调至10个,多则删,少则补,其值随机 a.resize(10,2);                      //将向量元素个数调至10个,多则删,少则补,其值为2 if(a==b) cout << “equal”;            //向量的比较操作还有!=,<,<=,>,>=

   向量与数组相比的好处是,其空间大小不需要提前指定,可以不断添加新的元素.但是,向量初始化时会分配一定的预留空间,如果添加元素的个数超过了预留空间,则需要扩容.内存意义上的扩容需要删除原空间并添加新的空间,这就必然增加向量操作的负担,因此在预计添加元素个数较多的情况下,我们还是需要给定向量的初始化大小.

   和数组类似,向量也存在2维向量乃至多维向量.我们通常使用 vector<vector<int>> 的形式声明一个2维向量,其一般操作和1维向量的方法是一致的.

 2)指针与引用

   c++的指针应用几乎是必不可少,我们将用较大篇幅来研究指针的用法.

 a.指针的定义

   如下的定义方式都是正确的

   int * p;

   char *cp;

   float* fp;

   double*dp;

   我们也可以定义一个二级指针

   int ** iip;

   但需要注意的是,一个*只能修饰一个指针,例如

   int* ip,iq;   //其中ip为指针变量,而iq为整形变量

   在指针初始化的过程中,有下面的形式:

   int* ip;

   int iCount = 18;

   int* iPtr = &iCount;       //初始化,&表示实体的地址,&后可以是一个变量,但不能是具体数值

   ip = &iCount;;              //赋值

   须注意,int ip = &iCount; 与 ip = &iCount; 并不相同,前者为初始化并赋值,后者本身形式错误.诸如 int iPtr; iPtr = 58;的语句也是毫无意义的.

 b.指针类型

  指针是有类型的,其类型也必须是一致的.在c语言中,有强制类型转换(int *),但事实上,c++有自身的强制转换函数.例如:

   int ip = reinterpret_cast<int>(&f);           //reinterpret的含义本身是” 重解释”,因而将float型指针无条件转换为整形指针.

 c.指针运算

   #include<iostream>    using namespace std;    int main(void){      int iArray[6];      for(int i=0;i<6;++i) iArray[i]= i2;      for(int iP=iArray; iP<iArray+6; iP+=1)      cout<<iP<<“: ”<<*iP<<endl;    }

   上面的程序例中,指针运算在数组中的应用已有了初步展现.同时对于不同类型的指针,相应的运算操作也有不同的数据变化.但是,在指针进行超过数组范围的操作时是非常危险的.

 d.指针限定

   我们知道,一个指针可以表示两个实体,即地址值和间仿值.因而,指针本身也分为指针常量和常量指针.

   const int a = 78;

   int b = 10;

   int c = 18;

   const int* ip = &a;                  //const 修饰指向的实体类型 常量指针 无法修改数值

   int const cp = &b;                 //const 修饰指针cp 指针常量 无法修改地址

   int const* dp = &b;                 //同上

   const int *const icp = &c;       //常量指针常量 均无法修改

 e.引用

   引用定义为:

   int someInt = 5,anyInt = 8;

   int & rInt = someIne;    //引用的作用类似别名,但值得注意的是, 如果重定义 rInt = anyInt,则rInt地址不变,值变为8,引用与指针的差别也就在于此了.即引用无法更改所引用的地址.通常我们也能使用const int & rInt = someIne使上述语句无法运行.但实体本身的操作someInt = 8同样能达到目的.

   引用的主要作用是进行参数传递,这在后文中将有较为详细深入的介绍.