C++从入门到起飞之——this指针 全方位剖析!

 

                                                                                个人主页:秋风起,再归来~

                                                                                           C++从入门到起飞                         

                                                                       个人格言:悟已往之不谏,知来者犹可追

                                                                                        克心守己,律己则安!

目录

1、this指针

2、C++和C语⾔实现Stack对⽐

C实现Stack代码

C++实现Stack代码

3.完结散花


1、this指针

class Data
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}

private:
	//这里只是声明,并没有开空间
	int _year;
	int _month;
	int _day;
};

• Date类中有Init与Print两个成员函数,函数体中没有关于不同对象的区分,那当d1调⽤Init和 Print函数时,该函数是如何知道应该访问的是d1对象还是d2对象呢?那么这⾥就要看到C++给了 ⼀个隐含的this指针解决这⾥的问题

• 编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this 指针。⽐如Date类的Init的真实原型为, void Init(Date* const this, int year, int month, int day)

• 类的成员函数中访问成员变量,本质都是通过this指针访问的,如Init函数中给_year赋值, this- >_year = year;

class Data
{
public:
	void Init(int year, int month, int day)
	{
		this->_year = year;
		this->_month = month;
		this->_day = day;
	}
	void Print()
	{
		cout << this->_year << "/" << this->_month << "/" << this->_day << endl;
	}

private:
	//这里只是声明,并没有开空间
	int _year;
	int _month;
	int _day;
};

• C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显 ⽰使⽤this指针。

1.下⾯程序编译运⾏结果是()

A、编译报错  B、运⾏崩溃 C、正常运⾏

class A
{
public:
	void Print()
	{
		cout << "A::Print()" << endl;
	}
private:
	int _a;
};

int main()
{
	A* p = nullptr;
	p->Print();
	return 0;
}

 答案是正常运行原因就在于我们对类类型进行操作(p->Print)时并不是对指针本身进行解引用操作,而是通过传参调用Print函数,我们只是传了空指针,并没有对空指针进行任何访问,所以程序不会报错。

2.下⾯程序编译运⾏结果是()

A、编译报错  B、运⾏崩溃  C、正常运⾏ 

class A
{
public:
	void Print()
	{
		cout << "A::Print()" << endl;
		cout << _a << endl;
	}
private:
	int _a;
};

int main()
{
	A* p = nullptr;
	p->Print();
	return 0;
}

我们看到程序并没有正常结束,所以答案是运行崩溃,原因在于函数调用时没有问题,但我们在函数执行期间对空指针进行了解引用(非法访问)

 而对于空指针的访问只有在运行时才会发生,而编译器在编译阶段时不会发现的,所以不是编译错误,而是运行时崩溃。

3.this指针存在内存哪个区域的()

A. 栈  B.堆  C.静态区  D.常量区  E.对象⾥⾯

答案是A!

在C++中,`this` 指针是一个隐含的指向当前对象的指针,它不是由程序员分配的,而是编译器自动创建并插入到每个成员函数的隐式参数列表中的。`this` 指针位于函数调用帧(call stack frame)的局部变量区,通常称为栈空间(Stack),用于存储函数执行时需要的临时数据和指向自身对象的数据。

当函数被调用时,`this` 指针会被初始化为指向调用它的对象实例,这对于访问类的私有成员变量特别有用。记住,`this` 永远不会为空,除非是在静态成员函数或者非成员函数中,这时没有特定的对象关联。

2、C++和C语⾔实现Stack对⽐

⾯向对象三⼤特性:封装、继承、多态,下⾯的对⽐我们可以初步了解⼀下封装。

通过下⾯两份代码对⽐,我们发现C++实现Stack形态上还是发⽣了挺多的变化,底层和逻辑上没啥变 化。 

C实现Stack代码

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;
void STInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}
void STDestroy(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}
void STPush(ST* ps, STDataType x)
{
	assert(ps);
	// 满了, 扩容
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->a, newcapacity *
			sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
	ps->a[ps->top] = x;
	ps->top++;
}
bool STEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}
void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	ps->top--;
}
STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	return ps->a[ps->top - 1];
}
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}
int main()
{
	ST s;
	STInit(&s);
	STPush(&s, 1);
	STPush(&s, 2);
	STPush(&s, 3);
	STPush(&s, 4);
	while (!STEmpty(&s))
	{
		printf("%d\n", STTop(&s));
		STPop(&s);
	}
	STDestroy(&s);
	return 0;
}

C++实现Stack代码

#include<iostream>
using namespace std;
typedef int STDataType;
class Stack
{
public:
	// 成员函数
	void Init(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = n;
		_top = 0;
	}
	void Push(STDataType x)
	{
		if (_top == _capacity)
		{
			int newcapacity = _capacity * 2;
			STDataType* tmp = (STDataType*)realloc(_a, newcapacity *
				sizeof(STDataType));
			if (tmp == NULL)
			{
				perror("realloc fail");
				return;
			}
			_a = tmp;
			_capacity = newcapacity;
		}
		_a[_top++] = x;
	}
	void Pop()
	{
		assert(_top > 0);
		--_top;
	}
	bool Empty()
	{
		return _top == 0;
	}
	int Top()
	{
		assert(_top > 0);
		return _a[_top - 1];
	}
	void Destroy()
	{
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	// 成员变量
	STDataType* _a;
	size_t _capacity;
	size_t _top;
};
int main()
{
	Stack s;
	s.Init();
	s.Push(1);
	s.Push(2);
	s.Push(3);
	s.Push(4);
	while (!s.Empty())
	{
		printf("%d\n", s.Top());
		s.Pop();
	}
	s.Destroy();
	return 0;
}

• C++中数据和函数都放到了类⾥⾯,通过访问限定符进⾏了限制,不能再随意通过对象直接修改数 据,这是C++封装的⼀种体现,这个是最重要的变化。这⾥的封装的本质是⼀种更严格规范的管 理,避免出现乱访问修改的问题。当然封装不仅仅是这样的,我们后⾯还需要不断的去学习。

• C++中有⼀些相对⽅便的语法,⽐如Init给的缺省参数会⽅便很多,成员函数每次不需要传对象地 址,因为this指针隐含的传递了,⽅便了很多,使⽤类型不再需要typedef⽤类名就很⽅便

• 在我们这个C++⼊⻔阶段实现的Stack看起来变了很多,但是实质上变化不⼤。等着我们后⾯看STL 中的⽤适配器实现的Stack,⼤家再感受C++的魅⼒。

3.完结散花

好了,这期的分享到这里就结束了~

如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

我们下期不见不散~~

​​​​

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-19 14:06:02       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-19 14:06:02       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-19 14:06:02       58 阅读
  4. Python语言-面向对象

    2024-07-19 14:06:02       69 阅读

热门阅读

  1. Binary Search

    2024-07-19 14:06:02       18 阅读
  2. C 语言实例 - 矩阵转换

    2024-07-19 14:06:02       20 阅读
  3. 升级TrinityCore 服务器硬件

    2024-07-19 14:06:02       19 阅读
  4. EasyExcel导入导出数据类型转换

    2024-07-19 14:06:02       19 阅读
  5. 第 4 课:Linux环境安装隐语Secretflow和Secretnote

    2024-07-19 14:06:02       19 阅读
  6. 音频播放:miniAudio 在QT框架使用, 数据源pcm

    2024-07-19 14:06:02       17 阅读
  7. Python常用的数据分析和可视化库

    2024-07-19 14:06:02       20 阅读
  8. C语言指针的理解

    2024-07-19 14:06:02       18 阅读
  9. Centos---命令详解 vi 系统服务 网络

    2024-07-19 14:06:02       21 阅读
  10. 基于深度学习的数据增强

    2024-07-19 14:06:02       20 阅读
  11. 【题解】StarryCoding P259 好奇怪好奇怪

    2024-07-19 14:06:02       21 阅读
  12. PHP 调用 JD 详情 API 接口:数据获取新途径

    2024-07-19 14:06:02       22 阅读
  13. 使用git提交代码时候出现403怎么解决

    2024-07-19 14:06:02       18 阅读