C++—指针和引用

指针

基本使用

  • 指针是一个值为内存地址的变量.

image-20200502162555918

语法: 数据类型 * 指针变量名;

int * ptr_num;
char* ptr_name;
float* money_ptr;
double* p_price;
  • 注意:
    • int* p 的写法偏向于地址, 即p就是一个地址变量, 表示一个十六进制的地址
    • int *p 的写法偏向于值, *p是一个整型变量, 能够表示一个整型值
    • 声明中的* 和使用中的 * 含义完全不一样.

取地址符&

image-20200502163046800

int num = 1024;
int* ptr_num;
//取num变量的地址复制给ptr_num
ptr_num = #

间接运算符*

image-20200502163220991

int num = 1024;
int* ptr_num;
ptr_num = #
*ptr_num = 1111;    //等价于 num = 1111;
#include <iostream>

using namespace std;

int main()
{
    double num = 1024.5;
    //定义一个指针, 并指向num变量
    double* ptr_num = &num;
    cout << "ptr_num的值: " << ptr_num << "t" << &num << endl;
    cout << "ptr_num指向空间的值:" << *ptr_num << endl;

    char ch = 'a';
    char* ptr_ch = &ch;
    cout << "ptr_ch的值: " << (void *)ptr_ch << "t" << "ptr_ch指向空间的值:" << *ptr_ch << endl;
    return 0;
}

空指针

  • 空指针不指向任何对象, 在试图使用一个指针之前可以首先检查是否为空
  • 尽量在定义了对象之后再定义指向它的指针
int *ptr1 = nullptr;  //等价于 int *ptr1 = 0;
int *ptr2 = 0;

//需要包含cstdlib
int *ptr3 = NULL;     //等价于 int *ptr3 = 0;

void * 指针

  • 一种特殊的指针类型, 可以存放任意对象的地址
  • void *指针存放一个内存地址, 地址指向的内容是什么类型不能确定
  • void *类型指针一般用来: 和别的指针比较, 作为函数的输入和输出, 赋值给另一个void *指针
double obj_num = 3.14;
double *ptr_obj = &obj_num;

cout << boolalpha;
void *vptr_obj = &obj_num;
cout << (ptr_obj == vptr_obj) << endl;

小结

  • 指针是一个变量, 存储的是另一个对象的内存地址
  • 如果一个变量存储了另一个对象的地址, 则称该变量指向这个对象
  • 指针变量可以赋值, 指针的指向在程序执行中可以改变
  • 指针变量的命名规则和其他变量的命名规则一样, 不能与现有变量同名
  • 若指针已声明指向某种类型数据的地址, 则不能用于存储其他类型数据的地址

引用

  • 为对象起的另外一个名字, 引用即别名
  • 引用并非对象, 只是为已经存在的对象起的别名
  • 引用只能绑定在对象上, 不能与字面值或某个表达式的计算结果绑定在一起
  • 引用必须初始化, 所以使用引用之前不需要测试其有效性, 因此使用引用可能会比使用指针效率高.
int value = 1024;
int& ref_value = value;

//错误, 引用必须初始化
int& ref_value2;

指针与引用

  • 引用对指针进行了简单的封装, 其底层仍然是指针

  • 获取引用地址时, 编译器会进行内部转换

    image-20200502182443969

指针与数组

  • 数组, 存储在一块连续的内存空间中

  • 数组名就是这块连续内存空间的首地址

    image-20200502182627627

#include <iostream>

using namespace std;

int main()
{
    double score[] {11, 22, 33, 44, 55};
    double * ptr_score = score;

    // 40   4
    cout << sizeof(score) << 't' << sizeof(ptr_score) << endl;
}

指针的算术运算

  • 一个类型为T的指针的移动, 以sizeof(T)为移动单位

image-20200502183052628

小结

  • 数组名就是这块连续内存单元的首地址
    • int num[50]; num是数组名, 也是数组的首地址
    • num的值与&num[0]的值相同
    • 数组的第i+1个元素的地址可表示为 num+i 或者 &num[i+1]
    • 数组的第i+1个元素的值可表示为 num[i] 或者 *(num+i)
    • 指针变量可以指向数组元素, int* ptr_num = &num[4] 或者 int * ptr_num = num + 4.

动态分配内存

使用new分配内存

  • 指针的真正用武之地是在运行阶段分配未命名的内存以存储值
  • 在这种情况下, 只能通过指针来访问内存

使用delete释放内存

  • 与new配对使用
  • 不要释放已经释放的内存
  • 不能释放声明变量分配的内存
//在运行阶段为int值分配未命名的内存, 使用指针来访问这个值
int* ptr_int = new int;

//释放由new分配的内存
delete ptr_int;

//注意: 不要创建两个指向同一内存块的指针, 有可能误删两次
int * ptr = new int;
int * ptr1 = ptr;
delete ptr;
delete ptr1;

动态分配数组

  • 使用new创建动态分配的数组, new运算符会返回第一个元素的地址

  • 使用delete[]释放内存, []表示释放整个数组

    int * ptr_int = new int;
    short * ptr_short = new short[500];
    delete ptr_int;
    delete [] ptr_short;
    
  • 注意:

    • 不要使用delete释放不是new分配的内存
    • 不要使用delete释放同一内存两次
    • 如果使用new[]为数组分配内存, 则对应delete[]释放内存
    • 对空指针使用delete是安全的
#include <iostream>

using namespace std;

int main()
{
    int num[5];                     //栈内存
    double* nums = new double[5];   //堆内存

    //  20    4
    cout << sizeof(num) << 't' << sizeof(nums) << endl;
}

程序的内存分配

  • 栈区
    • 由编译器自动分配释放, 一般存放函数的参数值, 局部变量的值
    • 操作方式类似数据结构中的栈, 先进后出
  • 堆区
    • 一般由程序员分配释放, 若程序不释放, 程序结束时可能会由操作系统回收
    • 注意, 与数据结构中的堆是两回事, 分配方式类似链表
  • 全局区(静态区)
    • 全局变量和静态变量存储在一起的
    • 程序结束后由系统释放
  • 文字常量去
    • 常量字符串就存放在这里, 程序结束由系统释放
  • 程序代码区
    • 存放函数体的二进制代码
//栈区
int num;

//栈区
char str[] = 'hello';

//栈区
char* ptr;

//hello以及在常量去, ptr2在栈区
char* ptr2 = "hello";

//全局初始化区
static inr num2 = 100;

//分配的内存在堆区, 但是ptr本身在栈区
ptr = new char[10];

小结

  • 指针是一个变量, 存储另一个对象的内存地址

  • 指针的声明由基本类型, 星号*和变量名组成

  • 为指针赋值, 赋值运算符右侧必须是一个地址

    • 如果是普通变量需要在前面加取地址运算符&
    • 如果是另一个指针变量或者一个数组, 不需要加&
  • 运算符*用于返回指针指向地址的内存地址中存储的值

  • 使用指针可以访问一维数组和二维数组的元素

//二维数组的创建和遍历
#include <iostream>

using namespace std;

int main()
{
    //使用指针创建二维数组
    int arrays[5][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9},
        {10, 11, 12},
        {13, 14, 15},
    };
    int (*p)[3] = arrays;

    for(int i = 0; i < 5; i++){
        for(int j = 0; j < 3; j++){
//            cout << *(*(p+i) + j) << ',';
            cout << *(*(p+i)+j) << ',';
        }
        cout << endl;
    }
}

原文链接: https://www.cnblogs.com/KX-Lau/p/12857542.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C++---指针和引用

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/347282

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午4:26
下一篇 2023年3月2日 上午4:26

相关推荐