第7章 指针
- 对象是用来存贮值的内存空间
- 使用&xx 获取对象xx的内存地址(使用取址运算符&获取对象的地址),可以使用sizeof获取对象的内存空间大小为多少字节,1字节=8位(1 byte = 8bit)。指针是为了有效的利用地址
- 用类型
int* pti;
定义指向int类型的指针,用pti=&i
初始化指针值,即: &i 创建了指向int的指针 - 指针的具体值是所指向对象的地址,
*pti
为解引用运算,得到的是指针pti所指对象的值,*pti
可以看作是变量i的别名 *
解引用运算不但可以指向值,也可以指向函数,把函数作为一个变量即可。- 未初始化指针的情况下会得到不可预知的结果
- 利用指针可以实现在运行时动态确定访问的对象
#include <iostream>
#include <typeinfo>
using namespace std;
int main() {
int i=1,j=2;
int* pti;
double d;
cout << "address if i:" << &i << ",size if i is:" << sizeof(i) << endl;
cout << "address if j:" << &j << ",size if j is:" << sizeof(i) << endl;
cout << "address if d:" << &d << ",size if d is:" << sizeof(d) << endl;
cout << endl;
pti = &i; cout << "pti=" << pti << ",*pti=" << *pti<<endl;
pti = &j; cout << "pti=" << pti << ",*pti=" << *pti << endl;
cout << endl;
cout << "type of i:" << typeid(i).name() << endl;
cout << "type of &i:" << typeid(&i).name() << endl;
cout << "type of pti:" << typeid(pti).name() << endl;
cout << "type of *pti:" << typeid(*pti).name() << endl;
return 0;
}
/*
address if i:0000004ECE9DF8E4,size if i is:4
address if j:0000004ECE9DF904,size if j is:4
address if d:0000004ECE9DF948,size if d is:8
pti=0000004ECE9DF8E4,*pti=1
pti=0000004ECE9DF904,*pti=2
type of i:int
type of &i:int * __ptr64
type of pti:int * __ptr64
type of *pti:int
*/
用地址作为函数参数,可以实现对调用函数传入的参数的原始值的修改:
#include <iostream>
using namespace std;
void sum_times(int x, int y, int* sum, int* times) {
// sum,times 为调用该函数的原始函数的两个变量的地址
// 计算x,y 的和、乘积,并传给调用函数的 sum,times 两个变量
*sum = x + y;
*times = x * y;
}
int main() {
int i=5,j=6;
int s,t;
double d;
sum_times(i, j, &s, &t);
cout << "s=" << s << endl;
cout << "t=" << t << endl;
return 0;
}
/*
s=11
t=30
*/
指针和数组
-
一般情况下数组名即指针:数组名被解释为指向该数组的第一个元素的指针,即 a==&a[0]
-
sizeof(数组名) 返回数组整体大小而不是第一个元素大小
-
typeid(数组名)返回数组相关信息而不是第一个元素相关信息
-
&数组名是指向数组的整体指针,而不是指向第一个元素的指针
-
可以用数组名作为参数,在函数间传递数据
#include <iostream>
using namespace std;
void reverse(int a[],int len_a) {
//反转整数数组
//int len_a = sizeof(a) / sizeof(a[0]);// 不能在这里计算数组长度,会得到2
cout << "len of array:" << len_a << endl;
int temp;
for (int i = 0; i < len_a / 2; i++) {
temp = a[i];
a[i] = a[len_a - i - 1];
a[len_a - i - 1] = temp;
}
}
int main() {
int a[10];
int len_a = sizeof(a) / sizeof(a[0]);
for (int i = 0; i < 10; i++) a[i] = i + 1;
for (int i = 0; i < 10; i++) cout<<a[i]<<' ';
cout << endl;
reverse(a,len_a);
for (int i = 0; i < 10; i++) cout << a[i] << ' ';
return 0;
}
/*
1 2 3 4 5 6 7 8 9 10
len of array:10
10 9 8 7 6 5 4 3 2 1
*/
动态存储期
- 程序员自由的控制对象的生命周期: 用 new Type 创建Type对象,并返回对象的地址。(C语言中用malloc 和 free 分配、释放内存空间)
动态创建变量:
#include <iostream>
using namespace std;
int main() {
int* x; // 创建一个整数地址变量
int* y;
int* z;
x = new int; //把申请的int地址赋值给x, *x 即创建的对象的值
y = new int();
z = new int(20);
cout << "x:" << x << endl;
cout << "*x:" << *x << endl; //这时候是一个不可预期的值
*x = 10;
cout << "*x:" << *x << endl;
cout << "y:" << y << endl;
cout << "*y:" << *y << endl;
cout << "z:" << z << endl;
cout << "*z:" << *z << endl;
delete x, y, z; // 销毁创建的x指向的对象
//cout << "*x:" << *x << endl; // 编译并不会错误,运行会触发异常
return 0;
}
/*
x:000001CB87D66E30
*x:-842150451
*x:10
y:000001CB87D70820
*y:0
z:000001CB87D6EA90
*z:20
*/
动态创建数组:
#include <iostream>
using namespace std;
int main() {
//动态数组
double* array_double;
int len_a;
cout << "请输入浮点数组长度:" << endl;
cin >> len_a;
array_double = new double[len_a];//为数组分配空间
for (int i = 0; i < len_a; i++) {
array_double[i] = (i+1) * (i+1);
}
for (int i = 0; i < len_a; i++) {
cout<<array_double[i] <<" ";
}
cout << endl;
delete[] array_double;
return 0;
}
/*
请输入浮点数组长度:
20
1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400
*/
分配失败会抛出异常,对应的分配的内存上线并不是物理内存,而是虚拟内存上限。
#include <iostream>
using namespace std;
int main() {
//动态数组
double* array_double;
while (true) {
try {
array_double = new double[10000];//为数组分配空间
}
catch (bad_alloc) {
cout << "创建动态数组失败" << endl;
return 1;
}
}
}
分配失败,如果创建对象时指定 nothrow, 则返回空指针NULL而不是抛出异常。NULL 需要引入
#include <iostream>
#include <cstddef>
using namespace std;
int main() {
//动态数组
double* array_double;
while (true) {
array_double = new(nothrow) double[1000000];//为数组分配空间
if (array_double == NULL) {
cout << "动态数组创建失败" << endl;
return 1;
}
}
}
可以指向任意类型的指针类型 void*
- 可以赋值任意类型指针给
void*
类型指针 - 反过来需要进行显式的转换:
pi = reinterpret_cast<int*>(pv)
void*
只能保存指针,不能进行*pv 取值
#include <iostream>
using namespace std;
int main() {
int* pi;
void* pv;
int a = 5,b=10;
pi = &a;
pv = &b;
cout << *pi << endl;
cout << *(reinterpret_cast<int*>(pv)) << endl;
return 0;
}
/*
5
10
*/
第8章 字符串和指针
- 字符串变量最后以空字符结尾
- 空字符是字符编码为0的字符,字面量为转义字符 ‘\0’
- 字符串大小包含末尾的空字符
初始化字符串:
#include <iostream>
using namespace std;
int main() {
char s1[] = { 'a','b','c','\0' }; //逐个字符初始化,需要加结束标志 '\0';
char s2[] = { "abc" };
char s3[] = "abc";
char s4[6] = "abc";
char s5[] = "abc\0def";
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
cout << s4 << endl;
cout << s5 << endl;
return 0;
}
/*
abc
abc
abc
abc
abc
*/
page277
正文完