国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【c++】類和對象(二)this指針

這篇具有很好參考價值的文章主要介紹了【c++】類和對象(二)this指針。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

【c++】類和對象(二)this指針,c++筆記倉,c++

??個人主頁:Quitecoder

??專欄:c++筆記倉

【c++】類和對象(二)this指針,c++筆記倉,c++

朋友們大家好,本節(jié)內(nèi)容來到類和對象第二篇,本篇文章會帶領大家了解this指針

1.this指針

1.1this指針的引出

首先我們定義一個日期類date:

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(2005, 6, 23);
	d2.Init(2024, 3, 25);
	d1.Print();
	d2.Print();

	return 0;
}

我們來思考這么一個問題:

Date類中有 Init 與 Print 兩個成員函數(shù),函數(shù)體中沒有關(guān)于不同對象的區(qū)分,也就是說,d1和d2調(diào)用的是同一個函數(shù),那當d1調(diào)用 Init 函數(shù)時,該函數(shù)是如何知道應該設置d1對象,而不是設置d2對象呢

【c++】類和對象(二)this指針,c++筆記倉,c++
首先思考,這里打印函數(shù),訪問的變量是哪里的?

void Print()
	{
		cout << _year << "-" << _month << "-" << _day <<endl;
	}

這里訪問的是private聲明下的嗎?

private:
	int _year;
	int _month;
	int _day;

并不是,因為這里只是聲明,并沒有開辟空間,真正訪問的是實例化的d1,d2

private部分聲明的變量_year、_month、_day等,在類中只是進行了聲明,實際上并沒有為它們分配內(nèi)存空間。**內(nèi)存空間是在創(chuàng)建類的實例(也就是對象)**時為這些成員變量分配的。每個對象都有自己獨立的一套成員變量,占用各自的內(nèi)存空間

因此,當成員函數(shù)Print()通過this指針(隱式指向當前對象)訪問這些成員變量時,它實際上訪問的是調(diào)用這個成員函數(shù)的那個==特定對象(實例)==的成員變量。每個對象的_year、_month_day都存儲在各自獨立的內(nèi)存區(qū)域中,這些內(nèi)存區(qū)域是在對象被創(chuàng)建時隨對象一起分配的

那么我d1,d2如何找到這兩個函數(shù)呢?

這里就與隱含的this指針有關(guān)了

this指針是面向?qū)ο缶幊陶Z言中的一個特殊指針,它指向調(diào)用成員函數(shù)的那個對象。通過this指針,成員函數(shù)可以訪問調(diào)用它的那個對象的成員變量和成員函數(shù)this指針是隱式傳遞給成員函數(shù)的,是成員函數(shù)的一個隱含參數(shù)

【c++】類和對象(二)this指針,c++筆記倉,c++
可以理解為,編譯器處理后處理為上述的樣子,調(diào)用的地方,編譯器也會處理:

【c++】類和對象(二)this指針,c++筆記倉,c++
它會把調(diào)用對象當做形參進行傳遞

【c++】類和對象(二)this指針,c++筆記倉,c++
這里我們也能知道,為什么d1訪問能打印d1,d2訪問能打印d2

這個東西我們并不陌生,在前面數(shù)據(jù)結(jié)構(gòu)中我們也有學過:
【c++】類和對象(二)this指針,c++筆記倉,c++

1.2this指針的特性

  1. this指針是“成員函數(shù)”第一個隱含的指針形參,一般情況由編譯器通過ecx寄存器自動傳遞,不需要用戶傳遞
  2. this指針的類型:類類型* const,(Date* const this)即成員函數(shù)中,不能給this指針賦值,但是this指向的內(nèi)容可以被改變
    【c++】類和對象(二)this指針,c++筆記倉,c++

特點:

  1. 在形參和實參的位置,我們不能顯示寫出來
    【c++】類和對象(二)this指針,c++筆記倉,c++
  2. 在函數(shù)內(nèi)部可以使用

【c++】類和對象(二)this指針,c++筆記倉,c++

1.3思考題

一,this指針是存在哪里的?

【c++】類和對象(二)this指針,c++筆記倉,c++
不同的數(shù)據(jù)是存儲在不同的區(qū)域的,思考一下this指針是存在哪個區(qū)域的呢?

const int i = 0;
int j = 1;
cout << &i << endl;
cout << &j << endl;

c++中,const定義的變量是存儲在棧中的,我們可以打印它們的地址:

【c++】類和對象(二)this指針,c++筆記倉,c++
發(fā)現(xiàn)是相鄰的

const int i = 0;
int j = 1;
const char* p = "abcdefg";
cout << &i << endl;
cout << &j << endl;
cout << &p << endl;
cout << (void*)p << endl;

【c++】類和對象(二)this指針,c++筆記倉,c++
在C++中,變量和數(shù)據(jù)的存儲位置分為幾個區(qū)域,主要包括棧(Stack)、堆(Heap)、全局/靜態(tài)存儲區(qū)(Global/Static Area)和常量區(qū)(Constant Pool)。具體到提供的代碼示例中的變量,它們的存儲位置如下:

  1. const int i = 0;

    • i是一個常量整型變量。在C++中,const修飾的局部變量默認存儲在棧上,但是編譯器優(yōu)化可能會將其存儲在程序的只讀數(shù)據(jù)段中(常量區(qū)),尤其是當它被視為編譯時常量時。然而,取地址操作&i表明i必須在內(nèi)存中有實際的存儲位置,所以它很可能位于棧上,除非進行了特殊的優(yōu)化
  2. int j = 1;

    • j是一個非const局部變量,存儲在棧上。棧用于存儲局部變量和函數(shù)調(diào)用的上下文
  3. const char* p = "abcdefg";

    • 這里p是一個指針,指向一個字符串常量。字符串常量"abcdefg"存儲在常量區(qū)(也稱為字符串字面量區(qū)或只讀數(shù)據(jù)段),這是因為字符串字面量在程序的整個生命周期內(nèi)都不應被修改。而指針p本身(即存儲字符串地址的變量)作為局部變量,存儲在棧上
  • i(取決于編譯器優(yōu)化)和j存儲在棧上。
  • 字符串常量"abcdefg"存儲在常量區(qū)。
  • 指針p(存儲字符串常量的地址)存儲在棧上。

在上述的講解后,我們能夠推出this指針的存儲位置:this是一個形參,它指向調(diào)用該成員函數(shù)的對象,this指針在成員函數(shù)調(diào)用時需要被快速訪問并用于訪問對象的成員,所以我們推測它存儲在棧上

為了提高訪問速度,某些編譯器可能選擇將this指針存儲在某個寄存器中,尤其是在成員函數(shù)調(diào)用時。這實際上可以減少內(nèi)存訪問次數(shù),從而提高程序的執(zhí)行效率,寄存器是CPU內(nèi)部的極小量存儲器,具有非常高的數(shù)據(jù)訪問速度
【c++】類和對象(二)this指針,c++筆記倉,c++

二,判斷下面程序的運行結(jié)果(this能否是空指針?)

class A
{
public:
	void PrintA()
	{
		cout << "PrintA()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->PrintA();
	return 0;
}

【c++】類和對象(二)this指針,c++筆記倉,c++
我們發(fā)現(xiàn)它是可以正常運行的,我們接下來簡單分析一下

盡管p被初始化為nullptr,指向A類型對象的指針p是空的,但PrintA()函數(shù)只是打印一條消息,沒有訪問任何對象的成員變量。這種特殊情況下,代碼可運行,主要是因為成員函數(shù)的調(diào)用并沒有實際依賴于this指針指向的對象實例的狀態(tài)

因為PrintA()不訪問對象的任何成員變量,所以這個調(diào)用在技術(shù)上不需要訪問通過this指針指示的內(nèi)存地址。因此,對于這種不訪問任何成員變量的成員函數(shù),通過nullptr調(diào)用可能不會導致運行時錯誤

簡單來說,

void PrintA()
	{
		cout << "PrintA()" << endl;
	}

這串代碼傳遞空指針并沒有任何影響

接下來看下面的代碼:

class A
{
public:
	void PrintA()
	{
		cout << _a << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->PrintA();
	return 0;
}

【c++】類和對象(二)this指針,c++筆記倉,c++
這串代碼運行異常,因為這里訪問a是通過this->_a來實現(xiàn)的

1.4C語言和C++實現(xiàn)Stack的對比

c語言實現(xiàn)

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語言實現(xiàn)時,Stack相關(guān)操作函數(shù)有以下共性

  • 每個函數(shù)的第一個參數(shù)都是Stack*
  • 函數(shù)中必須要對第一個參數(shù)檢測,因為該參數(shù)可能會為NULL
  • 函數(shù)中都是通過Stack*參數(shù)操作棧的
  • 調(diào)用時必須傳遞Stack結(jié)構(gòu)體變量的地址

結(jié)構(gòu)體中只能定義存放數(shù)據(jù)的結(jié)構(gòu),操作數(shù)據(jù)的方法不能放在結(jié)構(gòu)體中,即數(shù)據(jù)和操作數(shù)據(jù)的方式是分離開的

c++實現(xiàn)

typedef struct Stack
{
	DataType* array;
	int capacity;
	int size;
}Stack;
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++中通過類可以將數(shù)據(jù)以及數(shù)據(jù)的方法進行完美結(jié)合,通過訪問權(quán)限可以控制那些方法在類外可以被調(diào)用,即封裝,在使用時就像使用自己的成員一樣,更符合人類對一件事物的認知。而且每個方法不需要傳遞Stack*的參數(shù)了,編譯器編譯之后該參數(shù)會自動還原,即C++中 Stack * 參數(shù)是編譯器維護的,C語言中需用用戶自己維護

感謝大家閱讀?。?!后續(xù)給大家?guī)砦鰳?gòu)函數(shù)和構(gòu)造函數(shù)有關(guān)內(nèi)容!文章來源地址http://www.zghlxwxcb.cn/news/detail-847267.html

到了這里,關(guān)于【c++】類和對象(二)this指針的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包