花式使用C/C++的指针

简介: 指针无疑是C/C++语言的精髓所在,用好了是把利剑,用不好就是一颗炸弹。指针出BUG了,分分钟会让你写程序崩溃今天被C++的指针搞混了,翻阅了很多资料,有点懂了。

指针无疑是C/C++语言的精髓所在,用好了是把利剑,用不好就是一颗炸弹。指针出BUG了,分分钟会让你写程序崩溃
img_0264bd1c9238f2b99d6d3943be219cdc.jpe

今天被C++的指针搞混了,翻阅了很多资料,有点懂了。赶快来做一下笔记。
先来使用一个最简单的指针

    int a = 10;
    int *p=&a;

这个没啥难度不会出错,接下来来个难点的

    int a = 10;
    int *p = &a;
    int **p1 = &p;

这个指针的指针是不是已经头皮发麻了,别急,还有更变态的——指针数组数组指针函数指针指针函数。这回是不是彻底懵了。
现在就开始一个个使用这些指针
首先要明确一点,指针数组和数组指针不是一个概念

int *p3[10];
这就定义了一个指针数组,
[]优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有10个指针类型的数组元素


int (*p4)[10];
这是一个数组指针,因为()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是10


int* fun(int a);
这样就声明了一 个指针函数,就是返回指针的函数,函数可以不返回任何值,也可以返回整型值,实型值,字符型值,当然也可以返回指针值。函数fun需要在函数体中返回一个int型的指针。


int (*fun)(int a);
这样就定义了一个指向函数的指针,可以通过这个指针来调用函数,注意,这个指针不能指向任意的函数,只能指向返回值是int,并且只有一个形参的函数。
这些都是C中指针的使用,到了C++中,指针遇到类和对象,遇到new和delete这两个运算符,稍有不慎就会内存泄漏。
说了这么多,现在开始研究C++中指针的使用问题
先来新建一个Test类
Test.h

#pragma once
class Test
{
public:
    Test();
    Test(int _a);
    ~Test();
    int a;
};

Test.cpp

#include "stdafx.h"
#include "Test.h"
#include <iostream>
using std::cout;
using std::endl;


Test::Test():Test(0)//委托构造函数
{
    cout << "调用委托构造函数给a赋值 0"<<endl;
}

Test::Test(int _a=10):a(_a)//构造初始化,形参默认值=10
{
    cout << "call function Test(int _a) "<<endl;
}


Test::~Test()
{
    cout << "delete Test  " << a << endl;
}

main.cpp

// main.cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "Test.h"
#include <stdlib.h>

int main()
{
    /*1
    创建Test的实例,指针t1指向实例*/
    Test *t1 = new Test(6);

    delete t1;
    t1 = nullptr;


    /*2
    创建3个test实例数组  指针t2指向数组的第一个元素,
    此时只能调用Test类的无参构造函数*/
    Test *t2 = new Test[3];

    delete[] t2;//释放 test的三个实例
    t2 = nullptr;

    /*3 
    在堆中创建3个(Test)类型的指针数组,t3指向这个数组;*/
    Test* *t3 = new Test*[3];
    for (int i = 0; i < 3; i++)
    {
        /*创建3个Test的实例,让t3数组中的元素(指针)指向创建的对象*/
        t3[i] = new Test(i + 10);
    }

    for (int i = 0; i < 3; i++)
    {
        /*释放 在堆中创建的三个Test的实例*/
        delete t3[i];
    }

    delete[] t3;//释放动态创建的指向Test实例的指针数组


    system("pause");
    return 0;
}

先来开一下最简单的一种对象指针Test *t1 = new Test(6); 这时定义了一个Test类型的指针t1,并让这个指针指向从堆中申请的内存(Test的实例)运行以下看看

img_59a631e62a40c3a58d06611c05fb33b5.png
1

没意外,Test的实例正常创建,正常释放了。
再来看一下第二种情况

Test *t2 = new Test[3];

delete[] t2;

现在定义了一个Test的指针t2,并且在堆中创建了3个Test的实例,放在一个数组中,指针t2指向了这个数组。运行看一下
img_6aed1f5f68afef4980d19f99523e7089.png
2

这时有一点要注意一下,这样new创建对象时只能调用Test类的默认无参构造函数,其他的函数不能调用。我们为了给a赋值,使用了委托构造函数(不太熟悉的同学可以忽略),从打印的结果来看,程序正常创建了Test的实例,也正常释放内存。
现在来看一下最复杂的一种情况

/*3 
在堆中创建3个(Test)类型的指针数组,t3指向这个数组;*/
Test* *t3 = new Test*[3];
    for (int i = 0; i < 3; i++)
    {
        /*创建3个Test的实例,让t3数组中的元素(指针)指向创建的对象*/
        t3[i] = new Test(i + 10);
    }

    for (int i = 0; i < 3; i++)
    {
        /*释放 在堆中创建的三个Test的实例*/
        delete t3[i];
    }

    delete[] t3;

是不是已经晕倒在电脑前了0.0     莫慌,先看一下运行结果

img_82314e6b393b8587713887225731e804.png
3

一步步来分析以下代码,首先看一下 Test* *t3 = new Test*[3];t3是一个指针,它指向了堆中的一个数组,这个数组的类型是 Test*的。 new Test*[3]在堆内存中创建了一个长度为3的 Test*的数组。重点 t3指向的是堆中的一个数组
第一个for循环中的 t3[i] = new Test(i + 10);是给 t3所指向的数组中的元素赋值,因为数组是 Test*类型的,所以可以指向Test类的实例。
第二个for循环中 delete t3[i];是把在堆内存中创建的Test 类的实例释放。因为 t3[i]是一个指针,而且是指针数组,也就是说 t3[i],是 t3指针指向的数组(在堆内存中)的一个元素,所以要把 t3指向的数组释放 delete[] t3;

好了先总结到这吧。项目我已经上传到码云,需要的可以下载

目录
相关文章
|
2天前
|
存储 C++ 索引
C++函数指针详解
【10月更文挑战第3天】本文介绍了C++中的函数指针概念、定义与应用。函数指针是一种指向函数的特殊指针,其类型取决于函数的返回值与参数类型。定义函数指针需指定返回类型和参数列表,如 `int (*funcPtr)(int, int);`。通过赋值函数名给指针,即可调用该函数,支持两种调用格式:`(*funcPtr)(参数)` 和 `funcPtr(参数)`。函数指针还可作为参数传递给其他函数,增强程序灵活性。此外,也可创建函数指针数组,存储多个函数指针。
|
10天前
|
编译器 C++
【C++核心】指针和引用案例详解
这篇文章详细讲解了C++中指针和引用的概念、使用场景和操作技巧,包括指针的定义、指针与数组、指针与函数的关系,以及引用的基本使用、注意事项和作为函数参数和返回值的用法。
14 3
|
1月前
|
C++
C++(十八)Smart Pointer 智能指针简介
智能指针是C++中用于管理动态分配内存的一种机制,通过自动释放不再使用的内存来防止内存泄漏。`auto_ptr`是早期的一种实现,但已被`shared_ptr`和`weak_ptr`取代。这些智能指针基于RAII(Resource Acquisition Is Initialization)原则,即资源获取即初始化。RAII确保对象在其生命周期结束时自动释放资源。通过重载`*`和`-&gt;`运算符,可以方便地访问和操作智能指针所指向的对象。
|
1月前
|
C++
C++(九)this指针
`this`指针是系统在创建对象时默认生成的,用于指向当前对象,便于使用。其特性包括:指向当前对象,适用于所有成员函数但不适用于初始化列表;作为隐含参数传递,不影响对象大小;类型为`ClassName* const`,指向不可变。`this`的作用在于避免参数与成员变量重名,并支持多重串联调用。例如,在`Stu`类中,通过`this-&gt;name`和`this-&gt;age`明确区分局部变量与成员变量,同时支持链式调用如`s.growUp().growUp()`。
|
2月前
|
存储 安全 C++
C++:指针引用普通变量适用场景
指针和引用都是C++提供的强大工具,它们在不同的场景下发挥着不可或缺的作用。了解两者的特点及适用场景,可以帮助开发者编写出更加高效、可读性更强的代码。在实际开发中,合理选择使用指针或引用是提高编程技巧的关键。
24 1
|
2月前
|
安全 NoSQL Redis
C++新特性-智能指针
C++新特性-智能指针
|
2月前
|
编译器 C++
virtual类的使用方法问题之在C++中获取对象的vptr(虚拟表指针)如何解决
virtual类的使用方法问题之在C++中获取对象的vptr(虚拟表指针)如何解决
|
2月前
|
存储 安全 编译器
C++入门 | auto关键字、范围for、指针空值nullptr
C++入门 | auto关键字、范围for、指针空值nullptr
51 4
|
3月前
|
存储 安全 C++
浅析C++的指针与引用
虽然指针和引用在C++中都用于间接数据访问,但它们各自拥有独特的特性和应用场景。选择使用指针还是引用,主要取决于程序的具体需求,如是否需要动态内存管理,是否希望变量可以重新指向其他对象等。理解这二者的区别,将有助于开发高效、安全的C++程序。
29 2
|
3月前
|
存储 安全 C++
浅析C++的指针与引用
虽然指针和引用在C++中都用于间接数据访问,但它们各自拥有独特的特性和应用场景。选择使用指针还是引用,主要取决于程序的具体需求,如是否需要动态内存管理,是否希望变量可以重新指向其他对象等。理解这二者的区别,将有助于开发高效、安全的C++程序。
25 3