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)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容