खोज…


टिप्पणियों

this पॉइंटर C ++ का एक कीवर्ड है, इसके बाद इसे लागू करने के लिए किसी लाइब्रेरी की जरूरत नहीं है। और this एक संकेतक है मत भूलना! तो आप ऐसा नहीं कर सकते:

 this.someMember();

जैसा कि आप तीर के प्रतीक का उपयोग करके सदस्य कार्यों या सदस्य चर से पहुंचते हैं -> :

this->someMember();

this सूचक की बेहतर समझ के लिए अन्य उपयोगी लिंक:

'यह' सूचक क्या है?

http://www.geeksforgeeks.org/this-pointer-in-c/

https://www.tutorialspoint.com/cplusplus/cpp_this_pointer.htm

इस सूचक

सभी गैर स्थिर सदस्य कार्यों एक छिपा पैरामीटर, वर्ग, नामित का एक उदाहरण के लिए एक सूचक है this ; यह पैरामीटर चुपचाप पैरामीटर सूची की शुरुआत में डाला जाता है, और पूरी तरह से संकलक द्वारा संभाला जाता है। वर्ग के एक सदस्य एक सदस्य समारोह के अंदर पहुँचा है, यह चुपचाप के माध्यम से पहुँचा है this ; यह संकलक को सभी उदाहरणों के लिए एक एकल गैर-स्थैतिक सदस्य फ़ंक्शन का उपयोग करने की अनुमति देता है, और सदस्य फ़ंक्शन को अन्य सदस्य कार्यों को बहुरूपिक रूप से कॉल करने की अनुमति देता है।

struct ThisPointer {
    int i;

    ThisPointer(int ii);

    virtual void func();

    int  get_i() const;
    void set_i(int ii);
};
ThisPointer::ThisPointer(int ii) : i(ii) {}
// Compiler rewrites as:
ThisPointer::ThisPointer(int ii) : this->i(ii) {}
// Constructor is responsible for turning allocated memory into 'this'.
// As the constructor is responsible for creating the object, 'this' will not be "fully"
// valid until the instance is fully constructed.

/* virtual */ void ThisPointer::func() {
    if (some_external_condition) {
        set_i(182);
    } else {
        i = 218;
    }
}
// Compiler rewrites as:
/* virtual */ void ThisPointer::func(ThisPointer* this) {
    if (some_external_condition) {
        this->set_i(182);
    } else {
        this->i = 218;
    }
}

int  ThisPointer::get_i() const { return i; }
// Compiler rewrites as:
int  ThisPointer::get_i(const ThisPointer* this) { return this->i; }

void ThisPointer::set_i(int ii) { i = ii; }
// Compiler rewrites as:
void ThisPointer::set_i(ThisPointer* this, int ii) { this->i = ii; }

एक निर्माता में, this सुरक्षित रूप से (स्पष्ट या स्पष्ट रूप से) किसी भी क्षेत्र का उपयोग करने के लिए उपयोग किया जा सकता है जो पहले से ही आरंभिक हो चुका है, या माता-पिता वर्ग में किसी भी क्षेत्र; इसके विपरीत, (स्पष्ट रूप से या स्पष्ट रूप से) किसी भी ऐसे क्षेत्र तक पहुँच प्राप्त करना जो अभी तक आरंभीकृत नहीं हुआ है, या किसी व्युत्पन्न वर्ग में कोई भी फ़ील्ड असुरक्षित है, (व्युत्पन्न वर्ग के निर्माण के कारण अभी तक निर्माण नहीं किया गया है, और इस प्रकार इसके क्षेत्र न तो आरम्भिक हैं और न ही मौजूदा हैं)। यह भी आभासी सदस्य कार्यों के माध्यम से कॉल करने के लिए असुरक्षित है this , निर्माता के रूप में किसी भी व्युत्पन्न वर्ग कार्यों विचार नहीं किया जाएगा (व्युत्पन्न वर्ग अभी तक निर्माण नहीं किया जा रहा है की वजह से, और इस तरह अपनी निर्माता अभी तक vtable अपडेट नहीं हो)।


यह भी ध्यान दें कि एक कंस्ट्रक्टर में, ऑब्जेक्ट का प्रकार वह प्रकार है जो कंस्ट्रक्टर निर्माण करता है। यह सही है भले ही वस्तु को एक व्युत्पन्न प्रकार घोषित किया गया हो। उदाहरण के लिए, उदाहरण के लिए, नीचे ctd_good और ctd_bad टाइप कर रहे हैं CtorThisBase अंदर CtorThisBase() , और टाइप CtorThis अंदर CtorThis() , भले ही उनके विहित प्रकार है CtorThisDerived । चूंकि बेस क्लास के आसपास अधिक व्युत्पन्न कक्षाएं बनाई जाती हैं, उदाहरण धीरे-धीरे वर्ग पदानुक्रम से गुजरता है जब तक कि यह अपने इच्छित प्रकार का पूरी तरह से निर्मित उदाहरण नहीं है।

class CtorThisBase {
    short s;

  public:
    CtorThisBase() : s(516) {}
};

class CtorThis : public CtorThisBase {
    int i, j, k;

  public:
    // Good constructor.
    CtorThis() : i(s + 42), j(this->i), k(j) {}

    // Bad constructor.
    CtorThis(int ii) : i(ii), j(this->k), k(b ? 51 : -51) {
        virt_func();
    }

    virtual void virt_func() { i += 2; }
};

class CtorThisDerived : public CtorThis {
    bool b;

  public:
    CtorThisDerived()       : b(true) {}
    CtorThisDerived(int ii) : CtorThis(ii), b(false) {}

    void virt_func() override { k += (2 * i); }
};

// ...

CtorThisDerived ctd_good;
CtorThisDerived ctd_bad(3);

इन वर्गों और सदस्य कार्यों के साथ:

  • अच्छे निर्माता में, ctd_good :
    • CtorThisBase CtorThis कंस्ट्रक्टर के प्रवेश करने के समय तक पूरी तरह से निर्मित होता है। इसलिए, s जबकि initialising एक वैध स्थिति में है i , और इस प्रकार पहुँचा जा सकता है।
    • i को j(this->i) तक पहुंचने से पहले आरंभीकृत किया जाता है। इसलिए, i j को इनिशियलाइज़ करते समय एक मान्य स्थिति में i , और इस प्रकार एक्सेस किया जा सकता है।
    • k(j) तक पहुँचने से पहले j को इनिशियलाइज़ किया जाता है। इसलिए, j k को आरंभीकृत करते समय एक वैध स्थिति में है, और इस प्रकार पहुँचा जा सकता है।
  • खराब कंस्ट्रक्टर में, ctd_bad :
    • k की शुरुआत j(this->k) तक पहुंचने के बाद की जाती है। इसलिए, k , j को इनिशियलाइज़ करते समय अमान्य स्थिति में है और इसे एक्सेस करने के लिए अपरिभाषित व्यवहार का कारण बनता है।
    • CtorThisDerived जब तक के बाद नहीं का निर्माण किया है CtorThis का निर्माण किया है। इसलिए, k को प्रारंभ करते समय b एक अमान्य स्थिति में है, और इसे एक्सेस करने से अपरिभाषित व्यवहार होता है।
    • ऑब्जेक्ट ctd_bad अभी भी CtorThis जब तक कि CtorThis() छोड़ नहीं देता, और CtorThisDerived() तक CtorThisDerived() CtorThisDerived का उपयोग करने के लिए अपडेट नहीं किया जाएगा। इसलिए, virt_func() CtorThis::virt_func() virt_func() को कॉल करेगा, भले ही यह कॉल करने का इरादा हो या CtorThisDerived::virt_func()

सदस्य डेटा तक पहुँचने के लिए इस सूचक का उपयोग करना

इस संदर्भ में, this सूचक का उपयोग पूरी तरह से आवश्यक नहीं है, लेकिन यह पाठक को आपके कोड को स्पष्ट कर देगा, यह दर्शाता है कि एक दिया गया फ़ंक्शन या चर वर्ग का सदस्य है। इस स्थिति में एक उदाहरण:

// Example for this pointer
#include <iostream>
#include <string>

using std::cout;
using std::endl;

class Class
{
  public:
    Class();
    ~Class();
    int getPrivateNumber () const;
  private:
    int private_number = 42;
};

Class::Class(){}
Class::~Class(){}

int Class::getPrivateNumber() const
{
    return this->private_number;
}

int main()
{
    Class class_example;
    cout << class_example.getPrivateNumber() << endl;
}

इसे यहां कार्रवाई में देखें।

सदस्य डेटा और पैरामीटर के बीच अंतर करने के लिए इस सूचक का उपयोग करना

यह मापदंडों से सदस्य डेटा को अलग करने के लिए एक वास्तविक उपयोगी रणनीति है ... आइए इस उदाहरण को लेते हैं:

// Dog Class Example
#include <iostream>
#include <string>

using std::cout;
using std::endl;

/*
* @class Dog
*   @member name
*       Dog's name
*   @function bark
*       Dog Barks!
*   @function getName
*       To Get Private
*       Name Variable
*/
class Dog
{
 public:
    Dog(std::string name);
    ~Dog();
    void  bark() const;
    std::string  getName() const;
 private:
    std::string name;
};

Dog::Dog(std::string name)
{
    /*
    *  this->name is the
    *  name variable from 
    *  the class dog . and
    *  name is from the 
    *  parameter of the function
    */
    this->name = name; 
}

Dog::~Dog(){}

void Dog::bark() const
{
  cout << "BARK" << endl;   
}

std::string  Dog::getName() const
{
    return this->name;
}


int main()
{
    Dog dog("Max");
    cout << dog.getName() << endl;
    dog.bark();
}

आप यहां देख सकते हैं कि कंस्ट्रक्टर में हम निम्नलिखित कार्य करते हैं:

this->name = name; 

यहां, आप देख सकते हैं कि हम पैरामीटर डॉग को क्लास डॉग (यह-> नाम) से प्राइवेट वेरिएबल के नाम पर असेम्बल कर रहे हैं।

उपरोक्त कोड का आउटपुट देखने के लिए: http://cpp.sh/75r7

यह पॉइंटर CV-Qualifiers है

this भी cv- योग्य हो सकता है, किसी भी अन्य सूचक के समान। हालांकि, this पैरामीटर को पैरामीटर सूची में सूचीबद्ध नहीं होने के कारण, इसके लिए विशेष सिंटैक्स की आवश्यकता होती है; सीवी-क्वालिफायर को पैरामीटर सूची के बाद सूचीबद्ध किया जाता है, लेकिन फ़ंक्शन के शरीर से पहले।

struct ThisCVQ {
    void no_qualifier()                {} // "this" is: ThisCVQ*
    void  c_qualifier() const          {} // "this" is: const ThisCVQ*
    void  v_qualifier() volatile       {} // "this" is: volatile ThisCVQ*
    void cv_qualifier() const volatile {} // "this" is: const volatile ThisCVQ*
};

जैसा कि this एक पैरामीटर है, एक फ़ंक्शन को this cv-qualifier (s) के आधार पर ओवरलोड किया जा सकता है

struct CVOverload {
    int func()                { return    3; }
    int func() const          { return   33; }
    int func() volatile       { return  333; }
    int func() const volatile { return 3333; }
};

जब this const ( const volatile सहित) होता है, तो फ़ंक्शन इसके माध्यम से सदस्य चर लिखने में असमर्थ होता है, चाहे वह स्पष्ट रूप से हो या स्पष्ट रूप से। इसका एकमात्र अपवाद mutable सदस्य चर है , जिसे कॉन्स्ट-नेस की परवाह किए बिना लिखा जा सकता है। इसके कारण, const का उपयोग यह इंगित करने के लिए किया जाता है कि सदस्य फ़ंक्शन ऑब्जेक्ट की तार्किक स्थिति को नहीं बदलता है (जिस तरह से ऑब्जेक्ट बाहरी दुनिया को दिखाई देता है), भले ही वह भौतिक स्थिति को संशोधित करता हो (जिस तरह से ऑब्जेक्ट को हुड के नीचे दिखता है )।

लॉजिकल स्टेट वह तरीका है जो ऑब्जेक्ट बाहरी पर्यवेक्षकों को दिखाई देता है। यह सीधे भौतिक अवस्था से जुड़ा नहीं है, और वास्तव में, भौतिक अवस्था के रूप में भी संग्रहीत नहीं किया जा सकता है। जब तक बाहर के पर्यवेक्षक कोई परिवर्तन नहीं देख सकते, तब तक तार्किक स्थिति स्थिर है, भले ही आप ऑब्जेक्ट में हर एक बिट को फ्लिप करें।

भौतिक स्थिति, जिसे बिटवाइज़ स्टेट के रूप में भी जाना जाता है, यह है कि ऑब्जेक्ट को मेमोरी में कैसे संग्रहीत किया जाता है। यह ऑब्जेक्ट का नॉटी-ग्रिट्टी, कच्चा 1s और 0s है जो इसके डेटा को बनाते हैं। एक वस्तु केवल शारीरिक रूप से स्थिर होती है यदि स्मृति में इसका प्रतिनिधित्व कभी नहीं बदलता है।

ध्यान दें कि सी ++ ठिकानों const तार्किक राज्य, नहीं शारीरिक स्थिति पर सत्ता।

class DoSomethingComplexAndOrExpensive {
    mutable ResultType cached_result;
    mutable bool state_changed;

    ResultType calculate_result();
    void modify_somehow(const Param& p);

    // ...

  public:
    DoSomethingComplexAndOrExpensive(Param p) : state_changed(true) {
        modify_somehow(p);
    }

    void change_state(Param p) {
        modify_somehow(p);
        state_changed = true;
    }

    // Return some complex and/or expensive-to-calculate result.
    // As this has no reason to modify logical state, it is marked as "const".
    ResultType get_result() const;
};
ResultType DoSomethingComplexAndOrExpensive::get_result() const {
    // cached_result and state_changed can be modified, even with a const "this" pointer.
    // Even though the function doesn't modify logical state, it does modify physical state
    //  by caching the result, so it doesn't need to be recalculated every time the function
    //  is called.  This is indicated by cached_result and state_changed being mutable.

    if (state_changed) {
        cached_result = calculate_result();
        state_changed = false;
    }

    return cached_result;
}

ध्यान दें कि आप तकनीकी रूप से इस्तेमाल कर सकते हैं, जबकि const_cast पर this यह गैर-सीवी-योग्य बनाने के लिए, तुम सच में, वास्तव में नहीं करना चाहिए, और का उपयोग करना चाहिए mutable बजाय। एक const_cast अपरिभाषित व्यवहार को लागू करने के लिए उत्तरदायी है जब किसी ऑब्जेक्ट पर उपयोग किया जाता है जो वास्तव में const , जबकि mutable का उपयोग करने के लिए सुरक्षित होने के लिए डिज़ाइन किया गया है। हालाँकि, यह संभव है कि आप इसे अत्यंत पुराने कोड में चला सकते हैं।

इस नियम का एक अपवाद const संदर्भ में गैर-सीवी-योग्य एक्सेसर्स को परिभाषित करना है; यदि ऑब्जेक्ट को गैर-सीवी-योग्य संस्करण कहा जाता है तो const नहीं होने की गारंटी है, यूबी का कोई जोखिम नहीं है।

class CVAccessor {
    int arr[5];

  public:
    const int& get_arr_element(size_t i) const { return arr[i]; }

    int& get_arr_element(size_t i) {
        return const_cast<int&>(const_cast<const CVAccessor*>(this)->get_arr_element(i));
    }
};

यह कोड के अनावश्यक दोहराव को रोकता है।


नियमित संकेत के साथ के रूप में, यदि this volatile ( const volatile सहित), तो इसे कैश किए जाने के बजाय इसे एक्सेस किए जाने पर हर बार मेमोरी से लोड किया जाता है। यह ऑप्टिमाइज़ेशन पर उतना ही प्रभाव डालता है जितना कि किसी अन्य पॉइंटर को volatile करने की घोषणा करना, इसलिए देखभाल की जानी चाहिए।


ध्यान दें कि यदि एक उदाहरण सीवी-योग्य है, केवल सदस्य कार्यों यह उपयोग करने के लिए अनुमति दी है सदस्य कार्यों जिसका हैं this सूचक कम से कम सीवी योग्य उदाहरण खुद के रूप में है:

  • गैर-सीवी उदाहरण किसी भी सदस्य कार्यों का उपयोग कर सकते हैं।
  • const इंस्टेंसेस const और const volatile फंक्शन्स को एक्सेस कर सकता है।
  • volatile उदाहरण volatile और const volatile कार्यों का उपयोग कर सकते हैं।
  • const volatile उदाहरणों का उपयोग कर सकते const volatile कार्य करता है।

इस के कुंजी सिद्धांतों में से एक है const शुद्धता

struct CVAccess {
    void    func()                {}
    void  func_c() const          {}
    void  func_v() volatile       {}
    void func_cv() const volatile {}
};

CVAccess cva;
cva.func();    // Good.
cva.func_c();  // Good.
cva.func_v();  // Good.
cva.func_cv(); // Good.

const CVAccess c_cva;
c_cva.func();    // Error.
c_cva.func_c();  // Good.
c_cva.func_v();  // Error.
c_cva.func_cv(); // Good.

volatile CVAccess v_cva;
v_cva.func();    // Error.
v_cva.func_c();  // Error.
v_cva.func_v();  // Good.
v_cva.func_cv(); // Good.

const volatile CVAccess cv_cva;
cv_cva.func();    // Error.
cv_cva.func_c();  // Error.
cv_cva.func_v();  // Error.
cv_cva.func_cv(); // Good.

यह पॉइंटर रेफरी-क्वालिफायर

सी ++ 11

करने के लिए इसी तरह this सीवी-क्वालिफायर, हम भी करने के लिए रेफरी-क्वालिफायर आवेदन कर सकते हैं *this । रेफरी-क्वालिफायर सामान्य और rvalue संदर्भ अर्थ विज्ञान के बीच चयन करने के लिए, संकलक या तो कॉपी या स्थानांतरित करें जिस पर अधिक उपयुक्त हैं निर्भर करता है अर्थ विज्ञान उपयोग करने की अनुमति उपयोग किया जाता है, और करने के लिए लागू कर रहे हैं *this के बजाय this

ध्यान दें कि संदर्भ सिंटैक्स का उपयोग करते हुए रेफरी-क्वालीफायर के बावजूद, this स्वयं अभी भी एक संकेतक है। यह भी ध्यान दें कि रेफ-क्वालिफायर वास्तव में *this प्रकार को नहीं बदलते हैं; उनका वर्णन करके उनके प्रभावों को समझना और समझना आसान है जैसे उन्होंने किया था।

struct RefQualifiers {
    std::string s;

    RefQualifiers(const std::string& ss = "The nameless one.") : s(ss) {}

    // Normal version.
    void func() &  { std::cout << "Accessed on normal instance "    << s << std::endl; }
    // Rvalue version.
    void func() && { std::cout << "Accessed on temporary instance " << s << std::endl; }

    const std::string& still_a_pointer() &  { return this->s; }
    const std::string& still_a_pointer() && { this->s = "Bob"; return this->s; }
};

// ...

RefQualifiers rf("Fred");
rf.func();              // Output:  Accessed on normal instance Fred
RefQualifiers{}.func(); // Output:  Accessed on temporary instance The nameless one

एक सदस्य समारोह में रेफरी-क्वालीफायर के साथ और उसके बिना दोनों अधिभार नहीं हो सकते; प्रोग्रामर को एक या दूसरे के बीच चयन करना होता है। शुक्र है, cv- क्वालीफायर को रेफ-क्वालिफायर के साथ संयोजन के रूप में इस्तेमाल किया जा सकता है, जिससे const रिलिटी नियमों का पालन किया जा सकता है।

struct RefCV {
    void func() &                {}
    void func() &&               {}
    void func() const&           {}
    void func() const&&          {}
    void func() volatile&        {}
    void func() volatile&&       {}
    void func() const volatile&  {}
    void func() const volatile&& {}
};


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow