《C++primer》学习笔记/第二章

复合类型

引用

引用(reference)不是对象,相反的,它只是给已存在的对象起的另外一个名字

引用的特点:
1.一个变量可取多个别名
2.引用必须初始化
3.引用只能在初始化的时候引用一次,不能重新赋值

//格式:  类型 &引用名=已定义对象名
int i=42;
int& p=i;   //p是i的另一个名字
int &q=i;   //&符号的位置可以是和int连在一起,也可和q连在一起
int &m;     //!!报错!!该引用没有初始化
int ii=q;   //获取引用的值

指针

指针(pointer)是对象,可以赋值和拷贝,它存放的还是某个对象的地址;指针可以解引用

指针的状态:
1.指向一个对象
2.执行紧邻对象的空间的下一个位置
3.空指针
4.无效的指针,上述情况之外的指针

int i=42;
int *p ;//定义一个int型对象的指针
p=&i;//将i的地址赋给p
std::cout<<*p; // * 是取出存在P指向地址的变量

没有初始化的指针会引发运行时错误,因为指针所占的内存空间的内容被视为一个地址值,而这个位置本是不存在的,或者这个位置有内容,但是这个内容被当做地址取访问了,这样就会导致程序崩溃

空指针
int *p1 = nullptr;   //等价于 int *p1 = 0;
int *p2 = 0;         //直接将p2初始化为字面常量0
//需要首先#include cstdlib
int *p3 = NULL;      //等价于 int *p3 = 0;
void*指针

void是一种特殊的指针类型,可以存放任意对象的地址。但是,与通常指针不同的是我们不清楚它对象的类型,这也就导致不能直接操作它指向的对象。从void的视角来看,内存空间仅仅是内存空间,无法访问内存空间中所存的对象。

void指针用途:
1.与其他指针比较
2.作为函数的输入和输出
3.赋值给另一个void
指针

探究:指针的赋值和引用的“赋值”
#include<iostream>
#include<stdlib.h>
using namespace std;
int i=42;
int j=50;
int k=60;
int &p=i;
int *q=&i;
 int main()
 {
	 cout<<"初始i的值及地址:"<<i<<"  "<<&i<<endl;
	 cout<<"p引用对象及地址:"<<p<<"  "<<&p<<endl;
	 cout<<"q指向对象及地址:"<<*q<<"  "<<q<<endl;
	 cout<<endl;
	 p=j; //对引用p操作
	 cout<<"   引用p等于j:"<<p<<"  "<<&p<<endl;
	 cout<<"此时i值及地址:"<<i<<"  "<<&i<<endl;
	 cout<<"此时j值及地址:"<<j<<"  "<<&j<<endl;
	 cout<<"此时指针q指向:"<<*q<<"  "<<q<<endl;
	 cout<<endl;
	 q=&k; //对指针q操作
	 cout<<"   指针q指向k:"<<*q<<"  "<<q<<endl;
	 cout<<"此时i值及地址:"<<i<<"  "<<&i<<endl;
	 cout<<"此时p引用对象:"<<p<<"  "<<&p<<endl;

	 system("pause");
 }

输出的结果:

初始i的值及地址:42  00359000
p引用对象及地址:42  00359000
q指向对象及地址:42  00359000

   引用p等于j:50  00359000
此时i值及地址:50  00359000
此时j值及地址:50  00359004
此时指针q指向:50  00359000

   指针q指向k:60  00359008
此时i值及地址:50  00359000
此时p引用对象:50  00359000

结论:
p是i的引用,“赋值”引用p令p=j,若引用可以赋值,p等于新的值的同时i值不变,但是从输出结果中看出,i=j;所以看似是对p赋值,实际是对对象i重新赋值,也就是说明了引用初始化后便和对象绑在了一起,引用不能重新赋值。引用的“赋值”实际是对它对象的重新赋值。
同样的观察指针,指针q原本指向i,指向i的地址,重新赋值后指向j,指向j的地址,且对i没有影响。说明,指针可以重新赋值

复合类型的声明

复合类型(compound type)
基本数据类型(base type)
声明符(declarator)

要坚持自己的编程风格,不要总是变来变去

//写法1
int* p1,*q1,j,k;  // * 只是修饰p1,对该声明语句中的其他变量不起作用
//写法2
int *p1,*q1,j,k;
//写法3
int *p1;
int *q1;
int j,k;
指向指针的指针

指针是内存中的对象,也和其他对象一样,有它的地址,所以允许将该指针的地址在存放到另一个指针里。通过*的个数可以区分指针级别。如以下代码,***表示指针的指针,***表示指向指针的指针的指针,以此类推。

代码如下

#include<iostream>
#include<stdlib.h>
using namespace std;
int i=42;
int *j=&i;
int **jj=&j;
int ***jjj=&jj;

 int main()
 {
	 cout<<*j<<endl;
	 cout<<*jj<<"  "<<**jj<<endl;
	 cout<<*jjj<<"  "<<**jjj<<"  "<<***jjj<<endl;
	 system("pause");
 }

输出结果:

42
00FD9000  42
00FD9004  00FD9000  42
指向指针的引用

同上,由于指针本身也是对象,所以也可以引用,它的形式为: *&r=j ; (j为指针)

代码如下:

#include<iostream>
#include<stdlib.h>
using namespace std;
int i=42;
int *j=&i;  //声明j时,*说明j是指针类型;而输出时 * 表示解引用,就是取出存放在指针里的地址所对应的变量
int *&r=j;  //r是指向指针j的引用,也就是r是j,*r是*j

 int main()
 {
	 cout<<j<<"  "<<*j<<endl;
	 cout<<r<<"  "<<*r<<endl;
	 system("pause");
 }

输出结果:

00169000  42
00169000  42

const限定符

const的好处就是避免程序运行过程中改变了变量的值,相当于是定义了一个常量,例如圆周率pi,我们就可以设定为const
const的特点:
创建const对象时必须初始化,一旦创建就不能再改变
const对象只能执行不改变其内容的操作
const对象的调用:
默认下,多个文件出现的同名const是相互独立的,如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字
多文件共享const对象,代码如下:

//file_1.cc文件
extern const int i=3.14; //定义并初始化const i
//file_1.h头文件
extern const int i;  //声明const i 
顶层const与底层const
const double pi=3.14;  //pi为常量,其值不能改变
double *ptr=&pi;  //报错:此处ptr为普通指针
const double *cptr=&pi;  //cptr指向双精度常量
*cptr=42;  //报错:不能给*cptr赋值

//通常,指针类型必须与其所指对象类型一致,但是有两种例外,一是允许一个指向常量的指针指向一个非常量对象:
double dval=3.14;  //dval是双精度浮点数,无const限定符,其值可改变
cptr=&dval;  //正确,但是不能通过cptr改变dval的值

顶层const表示指针本身是常量
底层const表示指针所指对象是常量

int i=42;
const int a=i;  //创建const对象并初始化
const int &r1=i;  //允许const int&绑定到一个普通int对象上
const int &r2=50;  //r2是一个常量引用
const int &r3=r1*2;  //r3是一个常量引用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值