தமிழ்

நவீன C++ ஸ்மார்ட் பாயிண்டர்களை (unique_ptr, shared_ptr, weak_ptr) ஆராய்ந்து, நினைவகக் கசிவுகளைத் தடுத்து, செயலி நிலைத்தன்மையை மேம்படுத்துங்கள். சிறந்த நடைமுறைகளைக் கற்றுக்கொள்ளுங்கள்.

C++ நவீன அம்சங்கள்: திறமையான நினைவக மேலாண்மைக்கு ஸ்மார்ட் பாயிண்டர்களைக் கையாளுதல்

நவீன C++ இல், நினைவகத்தை பாதுகாப்பாகவும் திறமையாகவும் நிர்வகிப்பதற்கு ஸ்மார்ட் பாயிண்டர்கள் இன்றியமையாத கருவிகளாகும். அவை நினைவகத்தை நீக்கும் செயல்முறையை தானியக்கமாக்கி, நினைவகக் கசிவுகள் மற்றும் தொங்கும் பாயிண்டர்களைத் தடுக்கின்றன, இவை பாரம்பரிய C++ நிரலாக்கத்தில் பொதுவான தவறுகளாகும். இந்த விரிவான வழிகாட்டி C++ இல் கிடைக்கும் பல்வேறு வகையான ஸ்மார்ட் பாயிண்டர்களை ஆராய்ந்து, அவற்றை எவ்வாறு திறம்பட பயன்படுத்துவது என்பதற்கான நடைமுறை உதாரணங்களை வழங்குகிறது.

ஸ்மார்ட் பாயிண்டர்களின் தேவையைப் புரிந்துகொள்ளுதல்

ஸ்மார்ட் பாயிண்டர்களின் பிரத்தியேக அம்சங்களைப் பற்றி அறிவதற்கு முன், அவை தீர்க்கும் சவால்களைப் புரிந்துகொள்வது அவசியம். பழமையான C++ இல், டெவலப்பர்கள் new மற்றும் delete ஐப் பயன்படுத்தி நினைவகத்தை கைமுறையாக ஒதுக்குவதற்கும் நீக்குவதற்கும் பொறுப்பாவார்கள். இந்த கைமுறை மேலாண்மை பிழைகளுக்கு வழிவகுக்கும், இதன் விளைவாக:

இந்த சிக்கல்கள் நிரல் செயலிழப்பு, கணிக்க முடியாத நடத்தை மற்றும் பாதுகாப்பு பாதிப்புகளை ஏற்படுத்தக்கூடும். ஸ்மார்ட் பாயிண்டர்கள், டைனமிக்காக ஒதுக்கப்பட்ட பொருட்களின் ஆயுட்காலத்தை தானாகவே நிர்வகிப்பதன் மூலம் ஒரு நேர்த்தியான தீர்வை வழங்குகின்றன, இது Resource Acquisition Is Initialization (RAII) கொள்கையைப் பின்பற்றுகிறது.

RAII மற்றும் ஸ்மார்ட் பாயிண்டர்கள்: ஒரு சக்திவாய்ந்த கலவை

ஸ்மார்ட் பாயிண்டர்களின் பின்னணியில் உள்ள முக்கிய கருத்து RAII ஆகும், இது வளங்கள் பொருள் உருவாக்கத்தின் போது பெறப்பட்டு, பொருள் அழிவின் போது வெளியிடப்பட வேண்டும் என்று கூறுகிறது. ஸ்மார்ட் பாயிண்டர்கள் ஒரு ரா பாயிண்டரை உள்ளடக்கிய வகுப்புகளாகும், மேலும் ஸ்மார்ட் பாயிண்டர் அதன் வரம்பை விட்டு வெளியேறும்போது சுட்டிக்காட்டப்பட்ட பொருளை தானாகவே நீக்கிவிடும். இது விதிவிலக்குகள் ஏற்பட்டாலும் நினைவகம் எப்போதும் நீக்கப்படுவதை உறுதி செய்கிறது.

C++ இல் உள்ள ஸ்மார்ட் பாயிண்டர்களின் வகைகள்

C++ மூன்று முதன்மை வகையான ஸ்மார்ட் பாயிண்டர்களை வழங்குகிறது, ஒவ்வொன்றும் அதன் தனித்துவமான பண்புகள் மற்றும் பயன்பாட்டு நிகழ்வுகளைக் கொண்டுள்ளன:

std::unique_ptr: பிரத்தியேக உரிமை

std::unique_ptr டைனமிக்காக ஒதுக்கப்பட்ட ஒரு பொருளின் பிரத்தியேக உரிமையைக் குறிக்கிறது. எந்த நேரத்திலும் ஒரு குறிப்பிட்ட பொருளுக்கு ஒரே ஒரு unique_ptr மட்டுமே சுட்டிக்காட்ட முடியும். unique_ptr அதன் வரம்பை விட்டு வெளியேறும்போது, அது நிர்வகிக்கும் பொருள் தானாகவே நீக்கப்படும். இது ஒரு பொருளின் ஆயுட்காலத்திற்கு ஒரு ஒற்றை সত্তை பொறுப்பாக இருக்க வேண்டிய சூழ்நிலைகளுக்கு unique_ptr ஐ சிறந்ததாக்குகிறது.

உதாரணம்: std::unique_ptr ஐப் பயன்படுத்துதல்


#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass(int value) : value_(value) {
        std::cout << "MyClass இந்த மதிப்புடன் உருவாக்கப்பட்டது: " << value_ << std::endl;
    }
    ~MyClass() {
        std::cout << "MyClass இந்த மதிப்புடன் அழிக்கப்பட்டது: " << value_ << std::endl;
    }

    int getValue() const { return value_; }

private:
    int value_;
};

int main() {
    std::unique_ptr<MyClass> ptr(new MyClass(10)); // ஒரு unique_ptr ஐ உருவாக்குகிறது

    if (ptr) { // பாயிண்டர் செல்லுபடியாகுமா என்று சரிபார்க்கிறது
        std::cout << "மதிப்பு: " << ptr->getValue() << std::endl;
    }

    // ptr அதன் வரம்பை விட்டு வெளியேறும்போது, MyClass பொருள் தானாகவே நீக்கப்படும்
    return 0;
}

std::unique_ptr இன் முக்கிய அம்சங்கள்:

உதாரணம்: std::movestd::unique_ptr உடன் பயன்படுத்துதல்


#include <iostream>
#include <memory>

int main() {
    std::unique_ptr<int> ptr1(new int(42));
    std::unique_ptr<int> ptr2 = std::move(ptr1); // உரிமையை ptr2 க்கு மாற்றுகிறது

    if (ptr1) {
        std::cout << "ptr1 இன்னும் செல்லுபடியாகும்" << std::endl; // இது செயல்படுத்தப்படாது
    } else {
        std::cout << "ptr1 இப்போது பூஜ்யமாக உள்ளது" << std::endl; // இது செயல்படுத்தப்படும்
    }

    if (ptr2) {
        std::cout << "ptr2 ஆல் சுட்டிக்காட்டப்பட்ட மதிப்பு: " << *ptr2 << std::endl; // வெளியீடு: ptr2 ஆல் சுட்டிக்காட்டப்பட்ட மதிப்பு: 42
    }

    return 0;
}

உதாரணம்: std::unique_ptr உடன் தனிப்பயன் நீக்கிகளைப் பயன்படுத்துதல்


#include <iostream>
#include <memory>

// கோப்பு கைப்பிடிகளுக்கான தனிப்பயன் நீக்கி
struct FileDeleter {
    void operator()(FILE* file) const {
        if (file) {
            fclose(file);
            std::cout << "கோப்பு மூடப்பட்டது." << std::endl;
        }
    }
};

int main() {
    // ஒரு கோப்பைத் திறக்கிறது
    FILE* file = fopen("example.txt", "w");
    if (!file) {
        std::cerr << "கோப்பைத் திறப்பதில் பிழை." << std::endl;
        return 1;
    }

    // தனிப்பயன் நீக்கியுடன் ஒரு unique_ptr ஐ உருவாக்குகிறது
    std::unique_ptr<FILE, FileDeleter> filePtr(file);

    // கோப்பில் எழுதுகிறது (விருப்பத்தேர்வு)
    fprintf(filePtr.get(), "வணக்கம், உலகமே!\n");

    // filePtr அதன் வரம்பை விட்டு வெளியேறும்போது, கோப்பு தானாகவே மூடப்படும்
    return 0;
}

std::shared_ptr: பகிரப்பட்ட உரிமை

std::shared_ptr டைனமிக்காக ஒதுக்கப்பட்ட ஒரு பொருளின் பகிரப்பட்ட உரிமையை செயல்படுத்துகிறது. பல shared_ptr நிகழ்வுகள் ஒரே பொருளைச் சுட்டிக்காட்டலாம், மேலும் அதைச் சுட்டிக்காட்டும் கடைசி shared_ptr அதன் வரம்பை விட்டு வெளியேறும்போது மட்டுமே பொருள் நீக்கப்படும். இது குறிப்பு எண்ணுதல் (reference counting) மூலம் அடையப்படுகிறது, இதில் ஒவ்வொரு shared_ptr உம் உருவாக்கப்படும்போது அல்லது நகலெடுக்கப்படும்போது எண்ணிக்கையை அதிகரித்து, அழிக்கப்படும்போது எண்ணிக்கையைக் குறைக்கிறது.

உதாரணம்: std::shared_ptr ஐப் பயன்படுத்துதல்


#include <iostream>
#include <memory>

int main() {
    std::shared_ptr<int> ptr1(new int(100));
    std::cout << "குறிப்பு எண்ணிக்கை: " << ptr1.use_count() << std::endl; // வெளியீடு: குறிப்பு எண்ணிக்கை: 1

    std::shared_ptr<int> ptr2 = ptr1; // shared_ptr ஐ நகலெடுக்கிறது
    std::cout << "குறிப்பு எண்ணிக்கை: " << ptr1.use_count() << std::endl; // வெளியீடு: குறிப்பு எண்ணிக்கை: 2
    std::cout << "குறிப்பு எண்ணிக்கை: " << ptr2.use_count() << std::endl; // வெளியீடு: குறிப்பு எண்ணிக்கை: 2

    {
        std::shared_ptr<int> ptr3 = ptr1; // ஒரு வரம்பிற்குள் shared_ptr ஐ நகலெடுக்கிறது
        std::cout << "குறிப்பு எண்ணிக்கை: " << ptr1.use_count() << std::endl; // வெளியீடு: குறிப்பு எண்ணிக்கை: 3
    } // ptr3 வரம்பை விட்டு வெளியேறுகிறது, குறிப்பு எண்ணிக்கை குறைகிறது

    std::cout << "குறிப்பு எண்ணிக்கை: " << ptr1.use_count() << std::endl; // வெளியீடு: குறிப்பு எண்ணிக்கை: 2

    ptr1.reset(); // உரிமையை வெளியிடுகிறது
    std::cout << "குறிப்பு எண்ணிக்கை: " << ptr2.use_count() << std::endl; // வெளியீடு: குறிப்பு எண்ணிக்கை: 1

    ptr2.reset(); // உரிமையை வெளியிடுகிறது, பொருள் இப்போது நீக்கப்பட்டுள்ளது

    return 0;
}

std::shared_ptr இன் முக்கிய அம்சங்கள்:

std::shared_ptr க்கான முக்கியக் கருத்தாய்வுகள்:

std::weak_ptr: உரிமையற்ற கண்காணிப்பாளர்

std::weak_ptr ஒரு shared_ptr ஆல் நிர்வகிக்கப்படும் ஒரு பொருளுக்கு உரிமையற்ற குறிப்பை வழங்குகிறது. இது குறிப்பு எண்ணுதல் பொறிமுறையில் பங்கேற்காது, அதாவது அனைத்து shared_ptr நிகழ்வுகளும் வரம்பை விட்டு வெளியேறும்போது பொருள் நீக்கப்படுவதைத் தடுக்காது. weak_ptr ஒரு பொருளை உரிமை கொள்ளாமல் கண்காணிக்க பயனுள்ளதாக இருக்கும், குறிப்பாக சுழற்சி சார்புகளை உடைக்க.

உதாரணம்: சுழற்சி சார்புகளை உடைக்க std::weak_ptr ஐப் பயன்படுத்துதல்


#include <iostream>
#include <memory>

class B;

class A {
public:
    std::shared_ptr<B> b;
    ~A() { std::cout << "A அழிக்கப்பட்டது" << std::endl; }
};

class B {
public:
    std::weak_ptr<A> a; // சுழற்சி சார்புகளைத் தவிர்க்க weak_ptr ஐப் பயன்படுத்துதல்
    ~B() { std::cout << "B அழிக்கப்பட்டது" << std::endl; }
};

int main() {
    std::shared_ptr<A> a = std::make_shared<A>();
    std::shared_ptr<B> b = std::make_shared<B>();

    a->b = b;
    b->a = a;

    // weak_ptr இல்லாமல், சுழற்சி சார்பு காரணமாக A மற்றும் B ஒருபோதும் அழிக்கப்படாது
    return 0;
} // A மற்றும் B சரியாக அழிக்கப்படுகின்றன

உதாரணம்: பொருளின் செல்லுபடியை சரிபார்க்க std::weak_ptr ஐப் பயன்படுத்துதல்


#include <iostream>
#include <memory>

int main() {
    std::shared_ptr<int> sharedPtr = std::make_shared<int>(123);
    std::weak_ptr<int> weakPtr = sharedPtr;

    // பொருள் இன்னும் இருக்கிறதா என்று சரிபார்க்கவும்
    if (auto observedPtr = weakPtr.lock()) { // பொருள் இருந்தால் lock() ஒரு shared_ptr ஐ வழங்கும்
        std::cout << "பொருள் உள்ளது: " << *observedPtr << std::endl; // வெளியீடு: பொருள் உள்ளது: 123
    }

    sharedPtr.reset(); // உரிமையை வெளியிடுகிறது

    // sharedPtr மீட்டமைக்கப்பட்ட பிறகு மீண்டும் சரிபார்க்கவும்
    if (auto observedPtr = weakPtr.lock()) {
        std::cout << "பொருள் உள்ளது: " << *observedPtr << std::endl; // இது செயல்படுத்தப்படாது
    } else {
        std::cout << "பொருள் அழிக்கப்பட்டுவிட்டது." << std::endl; // வெளியீடு: பொருள் அழிக்கப்பட்டுவிட்டது.
    }

    return 0;
}

std::weak_ptr இன் முக்கிய அம்சங்கள்:

சரியான ஸ்மார்ட் பாயிண்டரைத் தேர்ந்தெடுத்தல்

பொருத்தமான ஸ்மார்ட் பாயிண்டரைத் தேர்ந்தெடுப்பது நீங்கள் அமல்படுத்த வேண்டிய உரிமை சொற்பொருளைப் பொறுத்தது:

ஸ்மார்ட் பாயிண்டர்களைப் பயன்படுத்துவதற்கான சிறந்த நடைமுறைகள்

ஸ்மார்ட் பாயிண்டர்களின் நன்மைகளை அதிகரிக்கவும், பொதுவான தவறுகளைத் தவிர்க்கவும், இந்த சிறந்த நடைமுறைகளைப் பின்பற்றவும்:

உதாரணம்: std::make_unique மற்றும் std::make_shared ஐப் பயன்படுத்துதல்


#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass(int value) : value_(value) {
        std::cout << "MyClass இந்த மதிப்புடன் உருவாக்கப்பட்டது: " << value_ << std::endl;
    }
    ~MyClass() {
        std::cout << "MyClass இந்த மதிப்புடன் அழிக்கப்பட்டது: " << value_ << std::endl;
    }

    int getValue() const { return value_; }

private:
    int value_;
};

int main() {
    // std::make_unique ஐப் பயன்படுத்துக
    std::unique_ptr<MyClass> uniquePtr = std::make_unique<MyClass>(50);
    std::cout << "Unique பாயிண்டர் மதிப்பு: " << uniquePtr->getValue() << std::endl;

    // std::make_shared ஐப் பயன்படுத்துக
    std::shared_ptr<MyClass> sharedPtr = std::make_shared<MyClass>(100);
    std::cout << "Shared பாயிண்டர் மதிப்பு: " << sharedPtr->getValue() << std::endl;

    return 0;
}

ஸ்மார்ட் பாயிண்டர்கள் மற்றும் விதிவிலக்கு பாதுகாப்பு

ஸ்மார்ட் பாயிண்டர்கள் விதிவிலக்கு பாதுகாப்பிற்கு கணிசமாக பங்களிக்கின்றன. டைனமிக்காக ஒதுக்கப்பட்ட பொருள்களின் ஆயுட்காலத்தை தானாகவே நிர்வகிப்பதன் மூலம், ஒரு விதிவிலக்கு ஏற்பட்டாலும் நினைவகம் நீக்கப்படுவதை அவை உறுதி செய்கின்றன. இது நினைவகக் கசிவுகளைத் தடுத்து, உங்கள் செயலியின் ஒருமைப்பாட்டைப் பராமரிக்க உதவுகிறது.

ரா பாயிண்டர்களைப் பயன்படுத்தும்போது நினைவகம் கசியக்கூடிய பின்வரும் உதாரணத்தைக் கவனியுங்கள்:


#include <iostream>

void processData() {
    int* data = new int[100]; // நினைவகத்தை ஒதுக்குகிறது

    // விதிவிலக்கை ஏற்படுத்தக்கூடிய சில செயல்பாடுகளைச் செய்கிறது
    try {
        // ... potentially exception-throwing code ...
        throw std::runtime_error("Something went wrong!"); // எடுத்துக்காட்டு விதிவிலக்கு
    } catch (...) {
        delete[] data; // catch தொகுதியில் நினைவகத்தை நீக்குகிறது
        throw; // விதிவிலக்கை மீண்டும் எறிகிறது
    }

    delete[] data; // நினைவகத்தை நீக்குகிறது (விதிவிலக்கு ஏற்படவில்லை என்றால் மட்டுமே அடையப்படும்)
}

முதல் delete[] data; கூற்றுக்கு *முன்* try தொகுதிக்குள் ஒரு விதிவிலக்கு ஏற்பட்டால், data க்காக ஒதுக்கப்பட்ட நினைவகம் கசிந்துவிடும். ஸ்மார்ட் பாயிண்டர்களைப் பயன்படுத்தி, இதைத் தவிர்க்கலாம்:


#include <iostream>
#include <memory>

void processData() {
    std::unique_ptr<int[]> data(new int[100]); // ஸ்மார்ட் பாயிண்டரைப் பயன்படுத்தி நினைவகத்தை ஒதுக்குகிறது

    // விதிவிலக்கை ஏற்படுத்தக்கூடிய சில செயல்பாடுகளைச் செய்கிறது
    try {
        // ... potentially exception-throwing code ...
        throw std::runtime_error("Something went wrong!"); // எடுத்துக்காட்டு விதிவிலக்கு
    } catch (...) {
        throw; // விதிவிலக்கை மீண்டும் எறிகிறது
    }

    // data வை வெளிப்படையாக நீக்கத் தேவையில்லை; unique_ptr அதை தானாகவே கையாளும்
}

இந்த மேம்படுத்தப்பட்ட எடுத்துக்காட்டில், unique_ptr ஆனது data விற்காக ஒதுக்கப்பட்ட நினைவகத்தை தானாகவே நிர்வகிக்கிறது. ஒரு விதிவிலக்கு ஏற்பட்டால், ஸ்டாக் அவிழ்க்கப்படும்போது unique_ptr இன் அழிப்பான் அழைக்கப்படும், இது விதிவிலக்கு பிடிக்கப்பட்டதா அல்லது மீண்டும் எறியப்பட்டதா என்பதைப் பொருட்படுத்தாமல் நினைவகம் நீக்கப்படுவதை உறுதி செய்கிறது.

முடிவுரை

பாதுகாப்பான, திறமையான மற்றும் பராமரிக்கக்கூடிய C++ குறியீட்டை எழுதுவதற்கான அடிப்படை கருவிகள் ஸ்மார்ட் பாயிண்டர்கள். நினைவக மேலாண்மையை தானியக்கமாக்குவதன் மூலமும், RAII கொள்கையை பின்பற்றுவதன் மூலமும், அவை ரா பாயிண்டர்களுடன் தொடர்புடைய பொதுவான தவறுகளை நீக்கி, மேலும் வலுவான செயலிகளுக்கு பங்களிக்கின்றன. பல்வேறு வகையான ஸ்மார்ட் பாயிண்டர்கள் மற்றும் அவற்றின் பொருத்தமான பயன்பாட்டு நிகழ்வுகளைப் புரிந்துகொள்வது ஒவ்வொரு C++ டெவலப்பருக்கும் அவசியமானது. ஸ்மார்ட் பாயிண்டர்களை ஏற்றுக்கொள்வதன் மூலமும், சிறந்த நடைமுறைகளைப் பின்பற்றுவதன் மூலமும், நீங்கள் நினைவகக் கசிவுகள், தொங்கும் பாயிண்டர்கள் மற்றும் பிற நினைவகம் தொடர்பான பிழைகளை கணிசமாகக் குறைக்கலாம், இது மேலும் நம்பகமான மற்றும் பாதுகாப்பான மென்பொருளுக்கு வழிவகுக்கும்.

சிலிக்கான் வேலியில் உள்ள ஸ்டார்ட்அப்கள் உயர் செயல்திறன் கணினிக்கு நவீன C++ ஐப் பயன்படுத்துவதிலிருந்து, உலகளாவிய நிறுவனங்கள் முக்கியத்துவம் வாய்ந்த அமைப்புகளை உருவாக்குவது வரை, ஸ்மார்ட் பாயிண்டர்கள் உலகளவில் பொருந்தக்கூடியவை. நீங்கள் இன்டர்நெட் ஆஃப் திங்ஸிற்கான உட்பொதிக்கப்பட்ட அமைப்புகளை உருவாக்கினாலும் அல்லது அதிநவீன நிதிச் செயலிகளை உருவாக்கினாலும், ஸ்மார்ட் பாயிண்டர்களைக் கையாளுவது சிறந்து விளங்க விரும்பும் எந்தவொரு C++ டெவலப்பருக்கும் ஒரு முக்கிய திறமையாகும்.

மேலும் கற்க