赞
踩
目录
- int *ptr_year;
- ptr_year=&year; //&year表示取地址
注意:
1. int* p的写法偏向于地址,即p就是一个地址变量,表示一个十六进制地址
2. int *p的写法偏向于值,*p是一个整形变量,能够表示一个整型值
3. 声明中的*号和使用中的*号含义完全不同
example:
- #include <iostream>
- using namespace std;
- int main()
- {
- char ch = 'a';
- char * ptr_ch = &ch;
- cout << (void *)ptr_ch << '\t' << *ptr_ch << endl;
- return 0;
- }
> 结果输出:0x6dfeeb a
(void *):任意类型指针
空指针不指向任何对象,在试图使用一个指针之前可以首先检查是否为空
用法
- int *ptr1 = nullptr;//等价于int *ptr1 = 0;
- int *ptr2 = 0; //直接将ptr2初始化为字面常量0
- //需要包含#include <stdlib.h>头文件
- int *ptr3 = NULL; //等价于int *ptr3=0;
1. (void*)指针存放一个内存地址,地址指向的内容是什么类型不能确定
2. (void*)类型指针一般用来:拿来和别的指针比较、作为函数的函数的输入和输出;赋值给另一个(void*)指针
- int int_value = 1024;
- //refValue指向int_value,是int_value的另一个名字
-
- int& refValue = int_value;
-
- //错误:引用必须被初始化
- int& refValue2;
注:
- double & ref = 100; //错误
- const double & ref = 100; //正确
引用并非对象,只是为一个已经存在的对象起的别名
int &ref_value = 10; //错误
引用必须初始化,所以使用之前不需要测试其有效性,因此使用引用可能会比使用指针效率高
int * num = &abc; //引用
引用更接近const指针,一旦与某个变量关联起来,就将一直效忠于它
将引用变量用作参数时,函数将使用原始数据,而非副本
当数据所占内存比较大时,建议使用引用参数
1. 引用对指针进行了简单封装,底层仍然是指针
2. 获取引用地址时,编译器会进行内部转换
3.引用比指针效率高
- int num = 108;
- int& rel_num = num;
- rel_num = 118;
- cout << &num << '\t' <<&rel_num <<endl;
转换为:
- int num = 108;
- int* rel_num = #
- *rel_num = 118;
- cout << &num << '\t' <<rel_num <<endl;
数组:
1. 存储在一块连续的内存空间中
2. 数组名就是这块连续内存空间的首地址
- #include <iostream>
- using namespace std;
- int main()
- {
- double score[] {11, 22, 33, 44, 55};//数组类型-->double[5]
- double * ptr_score = score;
-
- //数组名就是这块连续内存空间的首地址
- //cout << score << endl; //输出为地址值
- cout << sizeof(score) << ''\t' <<sizeof(ptr_score) <<endl
- }
结果:40 4
解答:ptr_score为double型的地址,所以只占4个字节;而score为数组,占40字节。
- int i;
- double score[5] {98, 87, 65, 43, 76};
- double * ptr_score;
- ptr_score = score;
- for(i=0;i<5; i++)
- {
- cout << (void*)ptr_score++ << endl;
- }
输出:
0x6dfec0
0x6dfec8
0x6dfed0
0x6dfed8
0x6dfee0
注:一个类型为T的指针的移动,以sizeof(T)为移动单元。因为score是double类型,所以每次移动8个字节空间
- int i;
- double score[5] {98, 87, 65, 43, 76};
- double * ptr_score;
- ptr_score = &score[1]; //取第一个数据的地址
- ptr_score +=2; //取第三个数据的地址
- cout << (void*)ptr_score++ << endl;
- ptr_score -=3; //取第一个数据的地址
- cout << (void*)ptr_score++ << endl;
结果:
0x6dfed8
0x6dfec8
int num[50]; //num是数组名,也可以理解成数组的首地址
num的值与&num[0]的值是相同的
数组第i+1个元素可表示为:
第i+1个元素的地址:
- &num[i+1]
- num+i+1
第i+1个元素的值:
- num[i+1]
- *(num+i+1)
- *++ptr_num
为指向数组的指针赋值:
- int * ptr_num = num;
- int * ptr_num = &num[0];
指针变量可以指向数组元素
- int * ptr_num = &num[4];
- int * ptr_num = num + 4;
如5行3列的二维数组指针首地址为&a[0][0]
使用指针访问二维数组元素中的元素
- *(a[1]+2); //表示a[1][2]
- *(*(a+1)+2); //表示a[1][2]
example1:
- #include <iostream>
- using namespace std;
-
- int main()
- {
- int * p = new int[10];
- //用指针创建二维数组
- int (*p2)[3] = new int[5][3];//降维操作//第一维已经降维,第二维3不变
- p2[3][2] = 555; //给其中一个赋值
-
- for(int i = 0; i<5; i++)
- {
- for(int j=0; j<3; j++)
- {
- //两种输出模式
- //cout << p2[i][j] << ',';
- cout << *(*(p2+i)+j) << ',';
- }
- cout << endl;
- }
- return 0;
- }

输出结果:
0,0,0,
0,0,0,
0,0,555,
0,0,0,
example2:
- #include <iostream>
- using namespace std;
-
- int main()
- {
- int * p = new int[10];
- //用指针创建二维数组
- int arrays[5][3] ={
- {1,2,3},
- {4,5,6},
- {7,8,9},
- {10,11,12},
- {13,14,15},
- };
- int (*p2)[3] = arrays;
- for(int i = 0; i<5; i++)
- {
- for(int j=0; j<3; j++)
- {
- //两种输出模式
- //cout << p2[i][j] << ',';
- cout << *(*(p2+i)+j) << ',';
- }
- cout << endl;
- }
- //输出每个元素的地址
- cout << &arrays[1][0] << endl;
- for(int i = 0; i<5; i++)
- {
- cout << p2 + i <<endl;
- }
- return 0;
- }

输出结果:
1,2,3,
4,5,6,
7,8,9,
10,11,12,
13,14,15,
0x6dfeac //arrays[1][0]输出元素地址
0x6dfea0
0x6dfeac arrays[1][0]输出元素地址
0x6dfeb8
0x6dfec4
0x6dfed0
- int * p = new int; //在运行此句话阶段分配未命名的内存
- int num; //此为编译阶段分配内存;
解析:p在栈区,在堆区分配一块int型空间
注:在运行阶段分配未命名的内存以存储值
delete ptr_int; //释放由new释放的内存
注:
与new配对使用;
不要释放已经释放的内存;
不能释放生命变量分配的内存;
不要创建两个指向同一内存块的指针,有可能误删除两次。
example:
- #include <iostream>
- using namespace std;
-
- int main()
- {
- int num[5];//分配了20字节的空间,即使空间里面没有数值;
- int* nums = new int[5]; //运行到这一步才在堆内存分配5个字节的整形空间,nums表明空间的地址大小
- cout << sizeof(num) << ''\t' <<sizeof(nums) <<endl
- }
运行结果:20 4
int * intArray = new int[10];
注:new运算符返回第一个元素的地址
delete [] intArray;//释放整个数组
example:
- int * ptr_int = new_int;
- short * ptr_short = new short[500];
- delete ptr_int; //释放由new释放的内存
- delete [] ptr_short;//释放整个数组
注:关于new和delete使用的规则:
不要使用delete释放不是new分配的内存
不要使用delete释放统一内存两次
如果使用new[]释放为数组分配内存,则对应delete[]释放内存
栈区(stack):由编译器自动分配释放,一般存放函数的参数值,局部变量的值等。其操作方式类似数据结构中的栈-先进后出。
堆区(heap):一般由程序员分配释放,若程序不释放,程序结束时可能由操作系统回收。其数据结构中的堆是两回事,分配方式类似链表。
全局区(静态区-static):全局变量和静态变量是存储在一起的,程序结束后由系统回收。
文字常量区:常量符号串就放在这里,程序结束由系统回收。
string a="hello,world!";
程序代码区:存放函数体的二进制代码。
注:
- #include <iostream>
- using namespace std;
- int num1 = 0;
- int * ptr1;
- int main
- {
- int num2; //栈区
- char str[] = "hello,world!";//栈区
- char * ptr2; //栈区
- char * ptr3 = "hello,world!"; //hello,world!以及\0在常量区,ptr3在栈区
- static int num3 = 1024; //全局(静态)初始化区
- ptr1 = new int[10]; //分配的内存在堆区
- ptr2 = new char[20];
- //注意:ptr1和ptr2本身在栈区
- return 0;
- }

1、指针是一个变量,存储另一个变量(对象)的内存地址
2、指针的声明由基本类型、星号(*)和变量名组成
3、为指针赋值,赋值运算符号右侧必须是一个地址
如果是普通变量需要在前面加一个取地址运算符&
如果是另一个指针变量或者是一个数组,不需要加&运算符
4、运算符*用于返回指针指向的内存地址中存储的值
5、使用指针访问一维数组和二维数组的元素
- int num = 4;
- int* p_num = #//取num所在的地址值
- *p_num = 112; //指向num的值变为112
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。