C/C++: pointer

  • 1 NULL
#define NULL  ((void *)0)

When NULL is assgined to a pointer, it means the pointer does not point to anything.

  • 2 void*
void *pv;

A pointer to void is a general-purpose pointer used to hold references to any data type.

Constants and Pointers

1 pointers to a constant

初始代码:

    int a = 2;
    const int b = 4;
    const int* pci;
    pci = &b;


调试分析:

  • pci可以改变自身的值,即指向另一个变量
    pci = &a;
  • *pci不允许改变指向的变量的值
    *pci = 8;     //error:  assignment of read-only location ‘* pci’
  • pci可以指向一个int或一个const int

  • pci的下述定义是等价的

  const int *pci;
  int const *pci;

简单图

  • 灰色表示不可通过指针的反引用改变变量的值
gg

2 constant pointers to nonconstant

初始代码

    int a = 2;
    const int b = 4;
    int c = 6;
    int* const cpi = &a;

调试分析

  • cpi必须在声明时就被初始化,否则会有如下报错
  int* const cpi;  //error: error: uninitialized const ‘cpi’
  cpi = &a;        //error: assignment of read-only variable ‘cpi’
  • cpi不能指向constant int
  int* const cpi = &b;   //error: invalid conversion from ‘const int*’ to ‘int*’
  • cpi不能改变自身的值,即在初始化后,不能指向另一个变量
  cpi = &c;    //error: assignment of read-only variable ‘cpi’
  • *cpi可以改变所指向的变量的值
  *cpi = 8; 

简单图

gg2

3 constant pointers to constants

初始代码:

    int a = 2;
    const int b = 4;
    const int* const cpci = &b;

调试分析:

  • cpci必须在声明时被初始化,否则会报错

  • cpci自身的值不允许被修改,即在初始化后不能指向另一个变量

  • *cpci不允许修改所指向变量的值

  • cpci可以指向一个int或是const int

简单图

gg3

4 pointer to constant pointer to constant

初始代码:

    const int b = 4;
    const int* const cpci = &b;
    const int* const* pcpci = &cpci;

调试分析:

    cout<<**pcpci<<endl;          // 4

简单图

gg4

& v.s. *(引用 v.s. 指针)

引用:就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。

1 传参

  • 引用传参
#include <iostream>

void add(int& sum, int a, int b)
{
    sum =  a + b;
}

int main()
{
    
    int a=3;
    int b=4;
    int c;
    add(c, a, b);
    std::cout<<c<<std::endl;

    return 0;
}

output:

7
  • 指针传参
#include <iostream>

void add(int* sum, int a, int b)
{
    *sum =  a + b;
}

int main()
{
    
    int a=3;
    int b=4;
    int c;
    add(&c, a, b);
    std::cout<<c<<std::endl;

    return 0;
}
  • 两种传参方式区别
  • 使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;
  • 使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元

2 常引用

初始代码:

    int a=3;
    const int& rci = a;

调试分析:

  • rci在初始化后就不能再被赋值了,但a仍可以被赋值
    rci = 1;     //error: assignment of read-only reference ‘rci’
    a = 1;       //that's okay.

传参常引用:

#include <iostream>

int add(int& a, int& b)
{
    return a+b;
}

int main()
{
    
    int a=3;
    int b=4;
    int c=add(a, b);

    return 0;
}
  • 上述代码是正确的,只是没什么意义,纯属为了测试。若在main函数加入
    int d=add(3, 4);  //error: invalid initialization of non-const reference of type ‘int&’ from an rvalue of type ‘int’

则将报错。那是因为int&的引用应该是变量,而不能是常数。

  • 为了能处理常数的情况,可以改下add函数
int add(const int& a, const int& b)
{
    return a+b;
}

这样,就可以了。除了能处理常数外,还有一个好处是,由于是常引用,故在该add函数内部不能改变a, b的原始值,更安全了。

3 引用作为返回值

#include <iostream>

const int& max(const int& a, const int& b)
{
    
    return a>b ? a:b;
}

int main()
{
    
    int a=3;
    int b=4;
    int c=max(a, b);
    std::cout<<c<<std::endl;

    return 0;
}
  • output:
4
  • 用引用返回一个函数值的最大好处是,在内存中不产生被返回值的副本。
  • 不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态

  • 再看下另一个例子:

#include<iostream>

int ga;

int double_1(int a)
{
    ga = 2*a;
    return ga;
}

int& double_2(int a)
{
    ga = 2*a;
    return ga;
}

int main()
{
    int a=2;
    int& b=double_2(a);
    b = 8;
    std::cout<<ga<<std::endl;

    return 0;
}

Output:

8

若在main中加上

    int& b = double_1(a);   //error: invalid initialization of non-const reference of type ‘int&’ from an rvalue of type ‘int’

将报错。因为double_1()函数返回的只是一个常数值,在C++中,任何临时变量都是常数值const,而int&引用的不能是常数值;但在double_2()函数中,函数返回的是ga,使得b引用它.

4 引用的其他特性

  • 传递性
#include <iostream>

int main()
{
    int a=3;
    int& b=a;
    int& c=b;
    c = 5;
    std::cout<<a<<std::endl;

    return 0;
}

Output:

5
  • int* &(指针引用) int* const&(指针常引用)
#include <iostream>

int main()
{
    int a=3;
    int* pi=&a;
    int*& rpi = pi;
    int* const& rcpi=&a;
    *rcpi = 6;

    std::cout<<a<<std::endl;

    return 0;
}

Output:

6

int*& rpi=&a; //error:因为&a为常量


- read more

**觅思.澈**同学的[C++引用详解](http://www.cnblogs.com/gw811/archive/2012/10/20/2732687.html)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容