zoukankan      html  css  js  c++  java
  • C++之指针与引用,函数和数组

    1. 引用:是对象的别名,其内部存放的时一个对象的地址,通过引用可以操纵对象,引用的所有操作实际上都是应用在它所指的对象身上,包括取地址操作符。引用的一些特性:
      • 引用定义时必须被初始化,引用一旦定义就不能再指向其他对象
      • const引用可以用不同类型的对象初始化,只要能从这种类型转换到引用类型,对于不可寻址的值如常量,编译器为了实现引用会生成一个临时对象,引用实际指向该对象,非const引用不能指向需要临时对象的对象或值,会导致编译错误
      • 不能定义引用类型的数组
      • 从上一点可以看出引用内部会存放一个内存地址,所以引用也是占内存的,但不能改变它的指向
      • 函数返回引用时要注意,引用不能指向函数的局部变量,因为在函数执行完后局部变量内存会被清空,所以引用的值会没有意义
    2. 指针:指针变量所存的内容时它指向的内存地址,用法有:
      • TYPE *ptr:定义一个指向TYPE的指针
      • TYPE *ptr[n]:定义一个指向TYPE的指针的数组
      • TYPE (*ptr)[n]:定义一个指向数组的指针,数组元素数目为n.ptr中存放的其实时数组第一个元素的地址,所以取数组中第一元素要用**ptr,两次解指针操作
        int arr[3]={1,2,3};
        //ptr是指针,该指针类型是int[3]
        int (*ptr)[3]=&arr;
        cout << **ptr << endl;//第一次解指针时得到数组地址,第二次解指针取数组中的值
      • TYPE **ptr:定义一个指向TYPE类型的指针的指
      • 空类型指针(void *)可以被任何类型数据指针类型的地址赋值,包括函数指针.由于不知道该地址的数据类型,所以不能操作空类型指针所指的对象,只能传送该地址或与其他地址值比较
        int add(int a,int b)
        {return a+b;}
        
        void *ptr = &add;//vs 2012编译通过
    3. 指针与函数:
      • TYPE (*ptr)(int,int):定义一个指向函数的指针,函数返回类型为TYPE,包含两个int参数。函数指针不是类型安全的,不同签名的函数指针之间能够强制转换,编译器能通过,但执行时候会出现不可预期的行为. 函数名其实时指向该类型函数的指针,将取地址符作用于函数名也能得到函数地址,如下add与&add是相同类型
        void add(int a,int b)
        {return ;}
        
        typedef int (*FunPtr)(int a,int b,int c);
        FunPtr func =(FunPtr)add;//编译能通过,执行时行为不可预期
      •  函数指针的数组:int(*Func[10])(int,int),Func是一个拥有10个元素的数组,每个元素都是一个指向函数的函数指针,这种定义方式可读性较差,可以使用如下方式
        typedef (*FuncPtr)(int,int)
        FuncPtr Func[10]
      • 返回类型为函数指针的函数:
        int(*func(int))(int *,int)//声明 一个函数func,返回类型为int (*)(int*,int)
        
        typedef int (*FuncPtr)(int *,int)//使用typedef提高代码可读性
        FuncPtr func(int *,int)
      • 要注意的是函数名不能作为函数的返回类型,只有函数指针可以,另外函数名作为参数传递给函数时,也会被转换为函数指针,对函数名也不能使用解指针操作符
    4. 指针与引用的区别:
      • 引用不能为空,指针可以
      • sizeof 引用得到的是变量的大小,sizeof指针得到的是指针本身的大小,任何指针类型在32位系统都是4字节
      • 引用时类型安全的,指针不是
    5. 指针与数组的关系:
      • 数组与指针是两种不同类型,数组有明确数量,指针只是个地址值.
      • 单独使用数组名时,编译器会把数组名转换为一个指针常量,指向数组中第一个元素的地址。对于二维数组数组名则是指针的指针
        int arr[3]={1,2,3}
        
        //如下语句作用一样
        int *ptr = arr;
        int *ptr=&arr[0]
        
        int arr[2][3]={{1,2,3},{4,5,6}}
        int (*ptr)[3];//定义一个指向数组的指针,数组元素数目为3
        ptr = &arr[1];
        
        cout << **p << endl 输出4,注意是两次解指针操作
      • 对于二维数组,数组名其实是一个指针,可以叫做行指针,该指针指向一个数组的首地址,数组元素数目为二维数组的列数.所以数组名也可以认为是指针的指针.
        int arr[2][3]={{1,2,3},{4,5,6}};
            cout <<"arr:    "<< arr << endl;    
            cout <<"arr+1:    " << arr+1 << endl;//第二行的地址
        
            cout << "*arr:    " << *arr << endl;
            cout << "*(arr+1):    " << *(arr+1) << endl;//第二行的首地址
        
            cout <<"arr[0]:    " << arr[0] << endl;
            cout <<"&arr[0]:    " << &arr[0] << endl;
            cout <<"&arr[0]+1:    " << &arr[0]+1 << endl;
        
            cout <<"arr[1]:    " << arr[1] << endl;
            cout <<"&arr[1]:    " << &arr[0]+1 << endl;

        image
  • 相关阅读:
    前端模块的前生今世
    variable fonts
    node
    webpack tree shaking
    es6 proxy浅析
    如何实现优美的骨架屏
    阿里巴巴Java开发手册建议创建HashMap时设置初始化容量,但是多少合适呢?
    新来个技术总监,禁止我们使用Lombok!
    2020年Java程序员应该学习的10大技术
    为啥HashMap的默认容量是16?
  • 原文地址:https://www.cnblogs.com/phenixyu/p/4246047.html
Copyright © 2011-2022 走看看