复合类型

合类型是指基于其他类型定义的类型。C++语言有几种符合类型,引用和指针

1、引用。(左值引用)

引用为对象起了另外一个名字,引用类型另外一种类型。通过声明符写成&d的形式来定义引用类型。其中d是生命的变量名。

int a=1024;

int &val=a;//val指向a(是a的另一个名字)

int &cal;//报错,引用必须被初始化

  一般在初始化变量时,初始值会被拷贝到新建的对象中。然而定义引用时,程序把引用和他的初始值绑定在一起,而不是将初始值拷贝给引用。一旦初始化完成,引用将和它的初始值对象一直绑定在一起。因为无法令引用重新绑定到另外一个对象,因此引用必须初始化。

引用即别名:引用并非对象,相反的,他只是为一个已经存在的对象所起的另外一个名字。

  定义了一个引用之后,对其进行的所有操作都是在与之绑定的对象上进行的。为引用赋值,实际上是把值赋给了与引用绑定的对象。获取引用的值,实际上是获取了与引用绑定的对象的值。

2、指针:

是指向另外一种类型的复合类型。与引用类似,指针也实现了对其他对象的间接访问。然而指针与引用相比又有很大的不同点。其一,指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它还可以先后指向几个不同的对象。其二,指针无需在定义时候就赋值,和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。

int * p;p是指向int类型对象的指针。

获取对象的地址:指针存放某个对象的地址,要想获取该地址,需要使用取地址符号(&)int val=24;int * p=&val;//p值存放变量val的内存地址,或者说p是指向变量val的指针。

因为在声明语句中指针类型实际上被用于指定他所指向对象的类型,所以二者必须匹配。

指针值:(即地址)因属于4种状态之一:

1、指向一个对象

2、指向紧邻对象所占空间的下一个位置。

3、空指针,没有指向任何对象。

4、无效指针

利用指针访问对象:如果指针指向了一个对象,则允许使用解引用符(*)来访问对象:int val=32;int * p=& val;cout<<*p;

解引用符只是应用于那些确实指向了某个对象的有效指针。

空指针:不知向任何对象,在试图使用一个指针之前代码首先检查他是否为空。

赋值与指针:指针和引用都能提供其他引用对象的简介访问,然而具体实现细节上二者有很大的不同,其中最重要的一点就是引用本身并非一个对象。一旦使用了引用,就无法令其在绑定到另外的对象,之后每次使用这个引用都是访问它最初绑定的那个对象。

指针和他存放的地址之间就没有这种限制。给指针赋值就是令他存放一个新的地址,从而指向一个对象:

int i=43;

int * p1=0;//p1被初始化没有指向对象

int * p2=& i;//p2被初始化,存有i的地址

int * p3;//这是个野的指针

p3=p2;//p3和p2指向同一个对象

p2=0;//p2不指向任何对象

注意:等号=永远改变的是等号左边的对象。

void *指针:

void* 是一种特殊的指针类型,可用于存放任意对象的地址。一个void*指针存放值一个地址,这一点和其他指针类似。不同的是,我们对该地址到底是个什么类型的的对象并不了解

指针和引用的主要区别:

指针和引用在C++中很常用,但是对于它们之间的区别很多初学者都不是太熟悉,下面来谈谈他们2者之间的区别和用法。

1.指针和引用的定义和性质区别:

(1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已。如:

int a=1;int *p=&a;

int a=1;int &b=a;

上面定义了一个整形变量和一个指针变量p,该指针变量指向a的存储单元,即p的值是a存储单元的地址。

而下面2句定义了一个整形变量a和这个整形a的引用b,事实上a和b是同一个东西,在内存占有同一个存储单元。

(2)可以有const指针,但是没有const引用;

(3)指针可以有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的)

(4)指针的值可以为空,但是引用的值不能为NULL,并且引用在定义的时候必须初始化;

(5)指针的值在初始化后可以改变,即指向其它的存储单元,而引用在进行初始化后就不会再改变了。

(6)"sizeof引用"得到的是所指向的变量(对象)的大小,而"sizeof指针"得到的是指针本身的大小;

(7)指针和引用的自增(++)运算意义不一样;

2.指针和引用作为函数参数进行传递时的区别。

(1)指针作为参数进行传递:

复制代码

#include<iostream>using namespace std;void swap(int *a,int *b)
{
  int temp=*a;
  *a=*b;
  *b=temp;
}int main(void)
{
  int a=1,b=2;
  swap(&a,&b);
  cout<<a<<" "<<b<<endl;
  system("pause");
  return 0;
}

复制代码

结果为2 1;

用指针传递参数,可以实现对实参进行改变的目的,是因为传递过来的是实参的地址,因此使用*a实际上是取存储实参的内存单元里的数据,即是对实参进行改变,因此可以达到目的。

再看一个程序;

复制代码

#include<iostream>using namespace std;void test(int *p)
{
  int a=1;
  p=&a;
  cout<<p<<" "<<*p<<endl;
}int main(void)
{
    int *p=NULL;
    test(p);
    if(p==NULL)
    cout<<"指针p为NULL"<<endl;
    system("pause");
    return 0;
}

复制代码

运行结果为:

0x22ff44 1

指针p为NULL

大家可能会感到奇怪,怎么回事,不是传递的是地址么,怎么p回事NULL?事实上,在main函数中声明了一个指针p,并赋值为NULL,当调用test函数时,事实上传递的也是地址,只不过传递的是指地址。也就是说将指针作为参数进行传递时,事实上也是值传递,只不过传递的是地址。当把指针作为参数进行传递时,也是将实参的一个拷贝传递给形参,即上面程序main函数中的p何test函数中使用的p不是同一个变量,存储2个变量p的单元也不相同(只是2个p指向同一个存储单元),那么在test函数中对p进行修改,并不会影响到main函数中的p的值。

如果要想达到也同时修改的目的的话,就得使用引用了。

2.将引用作为函数的参数进行传递。

在讲引用作为函数参数进行传递时,实质上传递的是实参本身,即传递进来的不是实参的一个拷贝,因此对形参的修改其实是对实参的修改,所以在用引用进行参数传递时,不仅节约时间,而且可以节约空间。

看下面这个程序:

复制代码

#include<iostream>using namespace std;void test(int &a)
{
  cout<<&a<<" "<<a<<endl;
}int main(void)
{
    int a=1;
    cout<<&a<<" "<<a<<endl;
    test(a);
    system("pause");
    return 0;
}

复制代码

输出结果为: 0x22ff44 1

          0x22ff44 1

再看下这个程序:

这足以说明用引用进行参数传递时,事实上传递的是实参本身,而不是拷贝。

所以在上述要达到同时修改指针的目的的话,就得使用引用了。

复制代码

#include<iostream>using namespace std;void test(int *&p)
{
  int a=1;
  p=&a;
  cout<<p<<" "<<*p<<endl;
}int main(void)
{
    int *p=NULL;
    test(p);
    if(p!=NULL)
    cout<<"指针p不为NULL"<<endl;
    system("pause");
    return 0;
}

复制代码

输出结果为:0x22ff44 1

         指针p不为NULL

原文地址:https://www.cnblogs.com/yjds/p/8597179.html