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

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

先来使用一个最简单的指针

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

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

1	int a = 10;
2	int *p = &a;
3	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

1#pragma once
2class Test
3{
4public:
5	Test();
6	Test(int _a);
7	~Test();
8	int a;
9};

Test.cpp

 1#include "stdafx.h"
 2#include "Test.h"
 3#include <iostream>
 4using std::cout;
 5using std::endl;
 6
 7
 8Test::Test():Test(0)//委托构造函数
 9{
10	cout << "调用委托构造函数给a赋值 0"<<endl;
11}
12
13Test::Test(int _a=10):a(_a)//构造初始化,形参默认值=10
14{
15	cout << "call function Test(int _a) "<<endl;
16}
17
18
19Test::~Test()
20{
21	cout << "delete Test  " << a << endl;
22}

main.cpp

 1// main.cpp: 定义控制台应用程序的入口点。
 2//
 3
 4#include "stdafx.h"
 5#include "Test.h"
 6#include <stdlib.h>
 7
 8int main()
 9{
10	/*1
11	创建Test的实例,指针t1指向实例*/
12	Test *t1 = new Test(6);
13
14	delete t1;
15	t1 = nullptr;
16
17
18	/*2
19	创建3个test实例数组  指针t2指向数组的第一个元素,
20	此时只能调用Test类的无参构造函数*/
21	Test *t2 = new Test[3];
22
23	delete[] t2;//释放 test的三个实例
24	t2 = nullptr;
25
26	/*3 
27	在堆中创建3个(Test)类型的指针数组,t3指向这个数组;*/
28	Test* *t3 = new Test*[3];
29	for (int i = 0; i < 3; i++)
30	{
31		/*创建3个Test的实例,让t3数组中的元素(指针)指向创建的对象*/
32		t3[i] = new Test(i + 10);
33	}
34
35	for (int i = 0; i < 3; i++)
36	{
37		/*释放 在堆中创建的三个Test的实例*/
38		delete t3[i];
39	}
40
41	delete[] t3;//释放动态创建的指向Test实例的指针数组
42
43
44	system("pause");
45	return 0;
46}

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

1

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

1Test *t2 = new Test[3];
2
3delete[] t2;

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

2

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

 1/*3 
 2在堆中创建3个(Test)类型的指针数组,t3指向这个数组;*/
 3Test* *t3 = new Test*[3];
 4	for (int i = 0; i < 3; i++)
 5	{
 6		/*创建3个Test的实例,让t3数组中的元素(指针)指向创建的对象*/
 7		t3[i] = new Test(i + 10);
 8	}
 9
10	for (int i = 0; i < 3; i++)
11	{
12		/*释放 在堆中创建的三个Test的实例*/
13		delete t3[i];
14	}
15
16	delete[] t3;

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

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;

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

发表了56篇文章 · 总计128.44k字
本博客已稳定运行
© QX
使用 Hugo 构建
主题 StackJimmy 设计