0
点赞
收藏
分享

微信扫一扫

力扣279. 完全平方数

木樨点点 2024-06-12 阅读 24

书接上回:【C++】类和对象(一)

文章目录

九、this指针

this指针的指出

我们先来看如下代码:

class Date
{
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;// 日
};

int main()
{
	Date d1, d2;
	d1.Init(2022, 1, 11);
	d2.Init(2022, 1, 12);
	d1.Print();
	d2.Print();
	return 0;
}

❓两个对象调用相同的Print()函数,但可以打印出各自对象成员变量的不同值,那编译器是如何知道本次调用是哪一个对象在调用该成员函数呢?

这就引出我们接下来的知识点——隐含的this指针

请添加图片描述

如果显示写出this指针如图:

请添加图片描述

其实C++跟C语言中的操作类似,只不过C++把调用函数时传参的工作,被调用函数接收参数的工作都交给编译器:

请添加图片描述

this指针的特性

1️⃣this指针是“成员函数”第一个隐含的指针形参,对象调用成员函数的时候不需要程序员传递对象的地址,一般情况由编译器通过ecx寄存器自动传递形参和实参的位置不能显示写,函数内部可以使用。

请添加图片描述

2️⃣this指针的类型本质有const的修饰:类类型* const,eg.(Date* const this)。不能给this指针赋值(改变this指针指向),但是this指向的内容可以被改变

在这里插入图片描述

面试题

❓this指针存在内存中的哪个区域

this指针是一个成员函数的形参,所以在函数栈帧里。

❓this指针可以为空吗

下面的代码运行结果是怎么样的?

// 1.下面程序编译运行结果是?  A、编译报错  B、运行崩溃  C、正常运行
class A
{
public:
    void PrintA()
    {
        cout << _a << endl;
    }
private:
    int _a;
};
int main()
{
    A* p = nullptr;
    p->PrintA();
    return 0;
}

在这里插入图片描述

答案:B.运行崩溃

p会做为实参传递给this指针,此时this指针为空,编译不会报错。但是cout << _a << endl这句代码对this指针指向对象的成员变量进行访问,则程序会崩溃。所以this指针不能为空

下图验证了this指针是空指针。

在这里插入图片描述

十、C语言和C++实现Stack的对比

C语言

typedef int DataType;
typedef struct Stack
{
	DataType* array;
	int capacity;
	int size;
}Stack;
void StackInit(Stack* ps)
{
	assert(ps);
	ps->array = (DataType*)malloc(sizeof(DataType) * 3);
	if (NULL == ps->array)
	{
		assert(0);
		return;
	}
	ps->capacity = 3;
	ps->size = 0;
}
void StackDestroy(Stack* ps)
{
	assert(ps);
	if (ps->array)
	{
		free(ps->array);
		ps->array = NULL;
		ps->capacity = 0;
		ps->size = 0;
	}
}
void CheckCapacity(Stack* ps)
{
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity * 2;
		DataType* temp = (DataType*)realloc(ps->array,
			newcapacity * sizeof(DataType));
		if (temp == NULL)
		{
			perror("realloc申请空间失败!!!");
			return;
		}
		ps->array = temp;
		ps->capacity = newcapacity;
	}
}
void StackPush(Stack* ps, DataType data)
{
	assert(ps);
	CheckCapacity(ps);
	ps->array[ps->size] = data;
	ps->size++;
}
int StackEmpty(Stack* ps)
{
	assert(ps);
	return 0 == ps->size;
}
void StackPop(Stack* ps)
{
	if (StackEmpty(ps))
		return;
	ps->size--;
}
DataType StackTop(Stack* ps)
{
	assert(!StackEmpty(ps));
	return ps->array[ps->size - 1];
}
int StackSize(Stack* ps)
{
	assert(ps);
	return ps->size;
}
int main()
{
	Stack s;
	StackInit(&s);
	StackPush(&s, 1);
	StackPush(&s, 2);
	StackPush(&s, 3);
	StackPush(&s, 4);
	printf("%d\n", StackTop(&s));
	printf("%d\n", StackSize(&s));
	StackPop(&s);
	StackPop(&s);
	printf("%d\n", StackTop(&s));
	printf("%d\n", StackSize(&s));
	StackDestroy(&s);
	return 0;
}

可以看到,在用C语言实现时,Stack相关操作函数有以下共性:

结构体中只能定义存放数据的结构,操作数据的方法不能放在结构体中,即数据和操作数据的方式是分离开的,而且实现复杂,涉及大量指针操作。

C++

typedef int DataType;
class Stack
{
public:
	void Init()
	{
		_array = (DataType*)malloc(sizeof(DataType) * 3);
		if (NULL == _array)
		{
			perror("malloc申请空间失败!!!");
			return;
		}
		_capacity = 3;
		_size = 0;
	}
	void Push(DataType data)
	{
		CheckCapacity();
		_array[_size] = data;
		_size++;
	}
	void Pop()
	{
		if (Empty())
			return;
		_size--;
	}
	DataType Top() { return _array[_size - 1]; }
	int Empty() { return 0 == _size; }
	int Size() { return _size; }
	void Destroy()
	{
		if (_array)
		{
			free(_array);
			_array = NULL;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	void CheckCapacity()
	{
		if (_size == _capacity)
		{
			int newcapacity = _capacity * 2;
			DataType* temp = (DataType*)realloc(_array, newcapacity *
				sizeof(DataType));
			if (temp == NULL)
			{
				perror("realloc申请空间失败!!!");
				return;
			}
			_array = temp;
			_capacity = newcapacity;
		}
	}
private:
	DataType* _array;
	int _capacity;
	int _size;
};
int main()
{
	Stack s;
	s.Init();
	s.Push(1);
	s.Push(2);
	s.Push(3);
	s.Push(4);
	printf("%d\n", s.Top());
	printf("%d\n", s.Size());
	s.Pop();
	s.Pop();
	printf("%d\n", s.Top());
	printf("%d\n", s.Size());
	s.Destroy();
	return 0;
}

C++中通过类可以将数据 以及 操作数据的方法放在一起,通过访问权限可以控制哪些方法在类外可以被调用,即封装,在使用时就像使用自己的成员一样,更符合人类对一件事物的认知。 而且每个方法不需要传递Stack*的参数了,编译器编译之后该参数会自动还原,即C++中 Stack * 参数是编译器维护的,C语言中需用用户自己维护

举报

相关推荐

0 条评论