C++ this 指針的具體使用
1.this指針的本質(zhì):一個(gè)隱藏的參數(shù)
首先,最關(guān)鍵的概念是:this 指針是一個(gè)隱含的、額外的參數(shù),由編譯器自動(dòng)添加到所有非靜態(tài)成員函數(shù)的參數(shù)列表中。
當(dāng)你定義一個(gè)成員函數(shù):
class MyClass { public: void setValue(int value) { // ... } };
編譯器在底層實(shí)際上會(huì)將它處理為類似這樣的形式:
void setValue(MyClass* this, int value) { // ... }
而當(dāng)你通過一個(gè)對(duì)象調(diào)用這個(gè)函數(shù)時(shí):
MyClass obj; obj.setValue(10);
編譯器會(huì)將它處理為:
setValue(&obj, 10); // 將 obj 的地址作為第一個(gè)參數(shù)(this)傳入
這就是 this
指針的由來——它指向調(diào)用該成員函數(shù)的那個(gè)對(duì)象的地址
2.this指針的核心特性
類型:this 指針的類型是 ClassName* const(一個(gè)指向 ClassName 的常量指針)。這意味著 this 指針本身的值(即它存儲(chǔ)的地址)不能被修改(你不能讓 this 指向另一個(gè)對(duì)象),但它所指向的對(duì)象的內(nèi)容可以被修改。
在 const 成員函數(shù) 中,this 指針的類型變?yōu)?nbsp;const ClassName* const,這意味著你不能通過 this 修改對(duì)象的數(shù)據(jù)成員(除非成員被 mutable 修飾)。
作用域:this 指針在類的非靜態(tài)成員函數(shù)內(nèi)部是局部的。它不能在成員函數(shù)體之外使用或定義。
存儲(chǔ):this 指針本身是一個(gè)函數(shù)參數(shù),因此它通常存儲(chǔ)在棧上(或者寄存器中,取決于調(diào)用約定),而不是對(duì)象本身的一部分。
3.this指針的主要應(yīng)用場景
場景一:解決命名沖突(最經(jīng)典用法)
當(dāng)成員函數(shù)的參數(shù)名與類的數(shù)據(jù)成員名相同時(shí),使用 this
來明確指明要訪問的是當(dāng)前對(duì)象的數(shù)據(jù)成員。
class Person { private: std::string name; int age; public: void setName(std::string name) { // 參數(shù)名與成員變量名相同 this->name = name; // 使用 this-> 來訪問成員變量 // name = name; // 錯(cuò)誤!這只是在給參數(shù)name自己賦值,成員變量未被修改 } void setAge(int age) { this->age = age; } };
場景二:在成員函數(shù)中返回對(duì)象本身(用于鏈?zhǔn)秸{(diào)用)
通過返回 *this
(對(duì) this
指針解引用),可以讓成員函數(shù)的調(diào)用串聯(lián)起來。
class Counter { int count; public: Counter() : count(0) {} // 返回 Counter& 非常重要,如果返回 Counter(值),鏈?zhǔn)秸{(diào)用中的每個(gè)操作都將作用于一個(gè)臨時(shí)副本 Counter& increment() { count++; return *this; // 返回當(dāng)前對(duì)象本身的引用 } Counter& decrement() { count--; return *this; } int getCount() const { return count; } }; int main() { Counter c; // 鏈?zhǔn)秸{(diào)用 (Chaining) c.increment().increment().decrement(); std::cout << c.getCount() << std::endl; // 輸出 1 return 0; }
場景三:在成員函數(shù)中傳遞對(duì)象自身
當(dāng)你需要在成員函數(shù)內(nèi)部將當(dāng)前對(duì)象作為一個(gè)參數(shù)傳遞給其他函數(shù)時(shí)。
class Server; // 前向聲明 class Client { public: void sendDataTo(Server& srv); }; class Server { public: void processRequest(Client& client) { // ... 處理來自 client 的請(qǐng)求 } }; void Client::sendDataTo(Server& srv) { // 將當(dāng)前 Client 對(duì)象傳遞給 Server 的 processRequest 方法 srv.processRequest(*this); // 使用 *this 傳遞對(duì)象本身 }
場景四:在數(shù)據(jù)結(jié)構(gòu)中實(shí)現(xiàn)自引用
在實(shí)現(xiàn)鏈表、樹等數(shù)據(jù)結(jié)構(gòu)時(shí),節(jié)點(diǎn)類中的成員函數(shù)經(jīng)常需要使用 this
來指代自身。
class ListNode { public: int data; ListNode* next; ListNode(int val) : data(val), next(nullptr) {} // 在當(dāng)前節(jié)點(diǎn)后插入一個(gè)新節(jié)點(diǎn) void insertAfter(int val) { ListNode* newNode = new ListNode(val); newNode->next = this->next; // 使用 this 明確表示當(dāng)前節(jié)點(diǎn)的 next 指針 this->next = newNode; } };
4.this指針的注意事項(xiàng)和進(jìn)階知識(shí)
靜態(tài)成員函數(shù)沒有 this 指針:
靜態(tài)成員函數(shù)屬于類本身,而不屬于任何一個(gè)特定的對(duì)象。因此,它沒有this
指針。這也意味著靜態(tài)成員函數(shù)不能直接訪問類的非靜態(tài)成員(因?yàn)闆]有對(duì)象實(shí)例可供操作)。this 指針與 Lambda 表達(dá)式:
在類的非靜態(tài)成員函數(shù)中定義的 Lambda 表達(dá)式,如果捕獲了this
指針(顯式或隱式捕獲),就可以通過該指針訪問類的成員。
class MyClass { int value = 42; public: void foo() { // 捕獲 this 指針,從而可以訪問成員變量 value auto lambda = [this]() { std::cout << this->value << std::endl; }; lambda(); } };
注意:如果 Lambda 的生命周期可能超過當(dāng)前對(duì)象(例如,被傳遞給另一個(gè)線程),捕獲 this
會(huì)導(dǎo)致懸空指針(Dangling Pointer),這是非常危險(xiǎn)的。在這種情況下,需要考慮弱引用或其他生命周期管理策略。
3.this 指針與智能指針:
當(dāng)你使用 std::shared_ptr 或 std::unique_ptr 管理對(duì)象時(shí),this 指針仍然是原始指針(raw pointer)。從一個(gè)共享指針管理的對(duì)象內(nèi)部獲取 this,并用它創(chuàng)建另一個(gè)共享指針,是極其錯(cuò)誤的,因?yàn)檫@會(huì)導(dǎo)致兩個(gè)獨(dú)立的控制塊,對(duì)象會(huì)被銷毀兩次。
C++標(biāo)準(zhǔn)庫提供了 std::enable_shared_from_this 來解決這個(gè)問題。
#include <memory> class Good : public std::enable_shared_from_this<Good> { public: std::shared_ptr<Good> getptr() { return shared_from_this(); // 正確地從 this 生成一個(gè) shared_ptr } }; int main() { std::shared_ptr<Good> gp1 = std::make_shared<Good>(); std::shared_ptr<Good> gp2 = gp1->getptr(); // 正確,共享所有權(quán) return 0; }
總結(jié)
特性/場景 | 描述 |
---|---|
本質(zhì) | 編譯器自動(dòng)傳遞給非靜態(tài)成員函數(shù)的隱藏參數(shù),指向調(diào)用該函數(shù)的對(duì)象。 |
類型 | ClassName* const(在 const 函數(shù)中是 const ClassName* const)。 |
解決命名沖突 | 使用 this->member 區(qū)分同名的參數(shù)和成員變量。 |
鏈?zhǔn)秸{(diào)用 | 返回 *this(返回對(duì)象引用)以實(shí)現(xiàn) obj.func1().func2() 的流暢接口。 |
傳遞自身 | 使用 *this 將當(dāng)前對(duì)象作為參數(shù)傳遞給其他函數(shù)。 |
靜態(tài)函數(shù) | 沒有 this 指針,因此不能訪問非靜態(tài)成員。 |
Lambda 捕獲 | 可以捕獲 this 來在 Lambda 內(nèi)部訪問成員,但需注意生命周期。 |
智能指針 | 直接使用 this 創(chuàng)建智能指針是危險(xiǎn)的,應(yīng)使用 std::enable_shared_from_this。 |
到此這篇關(guān)于C++ this 指針的具體使用的文章就介紹到這了,更多相關(guān)C++ this 指針內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ explicit關(guān)鍵字的應(yīng)用方法詳細(xì)講解
C++ explicit關(guān)鍵字用來修飾類的構(gòu)造函數(shù),表明該構(gòu)造函數(shù)是顯式的,既然有"顯式"那么必然就有"隱式",那么什么是顯示而什么又是隱式的呢?下面就讓我們一起來看看這方面的知識(shí)吧2013-09-09C語言用函數(shù)實(shí)現(xiàn)電話簿管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語言用函數(shù)實(shí)現(xiàn)電話簿管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12C語言數(shù)組學(xué)習(xí)之特殊矩陣的壓縮存儲(chǔ)
矩陣在計(jì)算機(jī)圖形學(xué)、工程計(jì)算中都占有舉足輕重的地位,本文將討論如何將矩陣更有效地存儲(chǔ)在內(nèi)存中,并且能夠方便地提取矩陣中的元素。感興趣的同學(xué)可以了解一下2021-12-12使用C++實(shí)現(xiàn)工資管理中的隨機(jī)教師信息生成功能
這篇文章主要介紹了使用C++實(shí)現(xiàn)工資管理中的隨機(jī)教師信息生成功能,想要做一個(gè)教師工資管理系統(tǒng),就必須得準(zhǔn)備好數(shù)據(jù),但是這些數(shù)據(jù)如果用手一行一行地敲,那么工作量是非常大的,因此,我就產(chǎn)生了用C語言實(shí)現(xiàn)直接生成大量的教師基本信息的想法,需要的朋友可以參考下2023-05-05