【C++学习记录】数组、指针、引用

数组
对于

int array[3];		int* ptr = array;

以下三行代码等价。

array[2];
*(ptr + 2);
*(int*)((char*)ptr + 8);

数组名有时可看做一个指针,(但数组名 != 指针)

 array = ptr;		//报错,数组名不能做修改
 int* ptr = &array ;		//报错,类型不匹配
 cout << &array ;		//可查看数组首个元素的地址

数组没有越界检查,在使用数组时要时刻注意数组的容量,避免越界。
出于效率考虑,数组作为形参传入函数后,会被当做指针处理。
当不得不使用数组作为函数形参时,得为函数增加一个参数用于提供数组的长度。

void checkSize(char a[])
{
cout << sizeof(a) << endl;
}
//输出4,为一个指针的大小

sizeof()如何得知数组的长度
来源:How does sizeof know the size of the operand array?
sizeof在编译阶段被诠释(interpreted),编译器知道数组如何被声明以及数组所占的空间。
“Calling sizeof on a dynamically-allocated array will likely not do what you want, because the end point of the array is not specified.”个人理解:数组没有结尾标记,所以应避免对运行阶段才创建的数组使用sizeof。

int  a1[5];
int *a2[5] = new int[5];
//都申请了20byte内存,a1申请在栈内存上,会自动释放;
					a2申请在堆内存上,需要手动释放。

指针
指针是一个整数(integer),一个数字,它存出一个内存的地址。一个指针所占内存大小与指针类型没有关系。
指针的类型决定了指针++时走过多少个字节。

指针的不正确使用经常会运行错误,所以应养成指针初始化的习惯。
空指针(int *p = nullptr)不能赋值。对空指针的赋值操作不会在编译阶段报错,程序运行时会崩溃。

指针的运算表达式
p++、++p和p+1
p++和++p都会使指针后移;p+1会返回指针后移后的位置,指针p不变 。
指针p具体后移多少字节(byte),取决于指针的类型。char类型后移1字节、int类型后移4字节、double类型后移8字节。
补充:自增(++)、自减(–)运算符的优先级高于解引用(*)运算符

int a[] = { 1,2,3,4,5 };
int* p = a;
cout << *(p++) << "   " << *p << endl;
cout << *(++p) << "   " << *p << endl;
int* q = a;
cout << *q++ << "   " << *q << endl;
cout << *++q << "   " << *q << endl;
//VS输出结果(前两行)
1 2 
3 3

void 类型指针(C++中很少使用)
void类型指针可以接收任何类型的指针,能转换为任何类型(“A void pointer can hold address of any type and can be typcasted to any type.”)
void指针可以被任意类型的指针赋值或初始化,但无法解引用,必须将其转换为任意一种数据类型后才能解引用。

不常用void类型指针的原因
在存取数据时,我们需要知道该数据占多少内存。对一个void指针赋值或初始化(如 void *ptr = 10;)会报错。因为编译器不知道该写入多少字节的数据,所以应该用带类型的指针告诉编译器。
(补充 :void *ptr = 0; 是允许的)

void 类型指针的用途
C语言中malloc() 和 calloc() 返回void类型指针,使得函数可以根据任意数据类型分配内存。但在C++中必须强制转换返回指针类型为需要的数据类型。

cosnt指针
const char * s 或 char const * s // 指针s所指向的数据的值不能修改
char * const p // 指针p不能修改
(记法:从左往右读,char类型->>指针->>常量,指针是常量,∴指针本身不能修改)

引用
引用能做的事情指针都能做,但如果条件允许,最好使用引用,因为它能使代码看起来更简单,更有可读性。
虽然有很多相似处,但引用不等于指针常量

int i;
int &ri = i;
int * const cpi = &i;
//不能将ri与cpi看做完全等价的变量

引用与指针的区别:
引用必须初始化;
引用初始化后无法修改;
引用无法指向nullptr;
无法创建引用数组……

https://www.geeksforgeeks.org/references-in-c/
拷贝构造函数中必须使用引用。
非法引用的两个例子:
1、

#include<iostream> 
using namespace std;
int main()
{
	int* ptr = NULL;
	int& ref = *ptr;
	cout << ref;
}

2、

#include<iostream> 
using namespace std;
int& fun()
{
	int x = 10;
	return x;
}
int main()
{
	fun() = 30;
	cout << fun();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值