【C++ Primer 第五版】复合类型

复合类型是指其他类型定义的类型
C++有集中复合类型,引用和指针是其中两种
复合类型变量的定义要复杂很多

1 引用

C++ 11包含左值引用和右值引用,一般的引用都是指左值引用
引用为对象另外一个名字,用&d的形式来定义

int ival = 1024;
int &refVal = ival; // refVal指向ival,是ival别名
int &refVal2; // 错误,引用必须初始化

程序将引用和它的初始值绑定,而不是将初始值拷贝给引用
完成初始化,则引用与初始值对象绑定在一起
引用必须初始化

#include <iostream>
int main()
{    
    int i = 1;
    int &a = i; // 正确,将a与i绑定在一起
    int &a = 1; // 错误,引用只能与对象绑定
    a = 10;     // 正确,相当于同时修改了a和i的值
    int &b = a; // 正确,再给a起别名b
    int &b = &a;// 错误,引用本身不是对象,不能定义引用的引用
    std::cout << i << std::endl;
    return 0;
}

允许一条语句定义多个引用,每个引用标识符必须以&开头
引用的类要与之绑定的对象严格匹配(有特例)
引用只能绑定对象,不能与字面值或表达式计算结果绑定

2.3.1 练习

  • 2.15判断定义合法性
    (a)int ival = 1.01; // 合法,但会强制转换为1
    (b)int &rvall = 1.01;//不合法,引用不能与字面值绑定
    (c)int &rval2 = ival;// 合法引用
    (d)int &rval3; // 不合法,引用必须初始化

  • 2.16 考察赋值合法性
    int i = 0, &r1 = i;
    double d = 0, &r2 = d;
    (a) r2 = 3.14159; // 合法
    (b) r2 = r1; // 合法
    © i = r2; // 合法
    (a) r1 = d; // 合法

  • 执行代码结果

#include <iostream>
int main()
{    
    int i, &ri = i;
    i = 5;
    ri = 10;
    std::cout << i << " " << ri << std::endl;
    return 0;
}

输出结果都是10,因为ri引用指向对象i,所以ri是i的别名,经过两次赋值,最终两个变量值都是10

2 指针

指针与引用相似,实现对象的简介访问
指针与引用不同在于,一是指针本身就是对象,允许赋值和拷贝,允许定义指向指针的指针,二是指针定义时可以不初始化

int *p1, *p2; //p1和p2都是指向int型对象的指针
double dp, *dp2;// dp2是指向double型对象的指针,dp是double型对象

指针存放某个对象的地址,要想获取该地址,需要使用取地址符&
int *p = &ival;意思是p是指向变量ival的指针,p存放变量ival的地址
因为引用不是对象,没有实际地址,所以不能定义指向引用的指针
指针类型和其所指向的对象类型必须相同(有特例)

指针的值(即地址)包含4种状态,指向一个对象、指向紧邻对象所占空间的下一位置、空控制、无效指针

int *val = 42;
double dp = &val;

指向对象的指针 dp存放变量val的地址,由解引用符*号访问dp指向对象
对指针解引用结果赋值,也是给指针所指向对象赋值

不同符号不同位置区分:

  • &出现在紧随类型名,是声明,定义引用
  • &出现在表达式,是取地址符
  • *出现在紧随类型名,是声明,定义指针
  • *出现在表达式,是解引用符
#include <iostream>
int main()
{    
    int i = 10;
    int *p = &i;
    int &r1 = *p; //正确,*p指向i,定义&r引用与对象*p(i)绑定
    int &r1 = p; // 错误,定义引用要与对象绑定,p的值是地址
    std::cout << r1  << std::endl;
    return 0;
}

空指针不指向任何对象,定义时可以初始化为nullptr、0、NULL
C++ 11最好使用nullptr,而不使用NULL
不能把变量直接付给指针
void是特殊的指针,可以存放任意对象的地址
指针符号
要与变量名紧挨在一起
**表示指向指针的指针
**表示指向指针的指针的指针

#include <iostream>
int main()
{    
    int i = 10;
    int *p1 = &i;
    int **p2 = &p1;
    // i的值是字面值,&i的值是i的地址
    std::cout << i << ',' << &i  << std::endl;
    // p1的值是i的地址(&i), &p1的值是指针p1的地址
    std::cout << p1<< ',' << &p1  << std::endl;
    // p2是指针p1的地址,*p2的值是i的地址,**p2是i
    std::cout << p2 << ',' << *p2  << std::endl;
    return 0;
}

引用并不是对象,所以不能定义指向引用的指针
指针是对象,可以定义对指针的引用

int i = 42;
int *p;      // p是一个int型指针
int *&r = p; // r是一个对指针p的引用
r = &i;      // r引用了一个指针,给r赋值相当于令指针p指向i
*r = 0; // 解引用r得到i,也就是p指向对象i的值进行修改

理解变量的类型,需要根据变量从紧挨变量从右往左识别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值