কিউটিতে মেমরি ম্যানেজমেন্ট?


97

আমি কিউটিতে বেশ নতুন এবং মেমরির পরিচালনা এবং অবজেক্টের জীবন নিয়ে কিছু বেসিক স্টাফ নিয়ে ভাবছি। কখন আমার জিনিসগুলি মুছতে এবং / বা ধ্বংস করতে হবে? এর কোনটি কি স্বয়ংক্রিয়ভাবে পরিচালিত হয়?

নীচের উদাহরণে, আমি তৈরি করা কোন বস্তুটি মুছতে হবে? উদাহরণটি পরিবর্তনশীলটির ধ্বংস হয়ে myOtherClassগেলে কী ঘটে myClass? আমি যদি আমার জিনিসগুলি একেবারে মুছে (বা ধ্বংস না করি) তবে কী হবে? স্মৃতিতে কি সমস্যা হবে?

মাইক্লাস

class MyClass
{

public:
    MyClass();
    ~MyClass();
    MyOtherClass *myOtherClass;
};

MyClass.cpp

MyClass::MyClass() {
    myOtherClass = new MyOtherClass();

    MyOtherClass myOtherClass2;

    QString myString = "Hello";
}

আপনি দেখতে পাচ্ছেন এটি বেশ নবাগত-সহজ স্টাফ তবে সহজেই আমি এই সম্পর্কে কোথায় শিখতে পারি?

উত্তর:


100

যদি আপনি QObjects এর সাথে নিজের নিজস্ব শ্রেণিবদ্ধতা তৈরি করেন , তবে, আপনি সমস্ত সৃজিতকে QObjectঅভিভাবকের সাথে আরম্ভ করেন ,

QObject* parent = new QObject();
QObject* child = new QObject(parent);

তারপর এটি করা যথেষ্ট , কারণ গুলি বিনাশকারী অন্তক যত্ন নিতে হবে । (এটি সিগন্যাল জারি করে এটি করে, তাই আপনি পিতামাতার আগে ম্যানুয়ালি মুছে ফেলা সত্ত্বেও এটি নিরাপদ ))deleteparentparentchildchild

আপনি প্রথমে শিশুটিকে মুছে ফেলতে পারেন, অর্ডার কোনও ব্যাপার নয়। একটি উদাহরণ যেখানে ক্রম জন্য করে ব্যাপার এখানে বস্তুর গাছ সম্পর্কে ডকুমেন্টেশন

যদি আপনার MyClassসন্তানের না হয় তবে QObjectআপনাকে প্লেইন সি ++ কাজ করার পদ্ধতি ব্যবহার করতে হবে।

এছাড়াও, নোট করুন যে পিতামাতাকৃত – চাইল্ড হায়ারার্কি QObjectসাধারণত সি ++ শ্রেণি শ্রেণিবিন্যাস / উত্তরাধিকার গাছের শ্রেণিবিন্যাসের থেকে পৃথক। এর অর্থ, একটি নির্ধারিত শিশুকে তার পিতামাতার সরাসরি সাবক্লাস হওয়ার দরকার নেই । যে কোনও (সাবক্লাস) QObjectযথেষ্ট হবে।

তবে অন্যান্য কারণে নির্মাণকারীরা আরোপিত কিছু প্রতিবন্ধকতা থাকতে পারে; যেমন ইন QWidget(QWidget* parent=0), যেখানে পিতামাতার অবশ্যই অন্য একজন থাকতে হবে QWidget, যেমন: দৃশ্যমানতার পতাকাগুলির কারণে এবং আপনি সেভাবে কিছু বেসিক লেআউটটি করতে চান; তবে সাধারণভাবে Qt এর শ্রেণিবিন্যাসের জন্য, আপনাকে QObjectপিতামাতার মতো কোনও অনুমতি দেওয়া হয় ।


21
(It does this by issuing signals, so it is safe even when you delete child manually before the parent.)-> এটি নিরাপদ থাকার কারণ নয়। Qt 4.7.4 এ, কিউবজেক্ট শিশুরা সরাসরি মুছে ফেলা হবে (মাধ্যমে delete, qobject.cpp, 1955 লাইনটি দেখুন)। শিশুদের অবজেক্টগুলি মুছে ফেলা নিরাপদ হওয়ার কারণটি হ'ল কোনও কিউবজেক্ট মুছে ফেলা হলে তার পিতামাতাকে এটি ভুলে যেতে বলে।
মার্টিন হেনিংস

4
আমি যুক্ত করব যে আপনার অবশ্যই বংশধরদের ধ্বংসকারীদের এটি সত্য হওয়ার জন্য ভার্চুয়াল রয়েছে তা নিশ্চিত করতে হবে। যদি ClassBউত্তরাধিকারসূত্রে থেকে QObjectএবং ClassCউত্তরাধিকার সূত্রে প্রাপ্ত হয় ClassB, তবে ClassCকেবলমাত্র Qt- র পিতা-সন্তানের সম্পর্কের দ্বারা সঠিকভাবে ধ্বংস হয়ে যাবে যদি ClassBএর ডেস্ট্রাক্টর ভার্চুয়াল হয়।
ফুলেসিয়াস

4
উত্তরের লিঙ্কটি এখন ভেঙে গেছে (প্রায় 4 বছর পরে অবাক হওয়ার কিছু নেই ...), সম্ভবত এটি কিউইটি-প্রজেক্ট.আর.কম / ডক্ট / কিউটি -৪..8/objecttrees.html এর মতো ?
পিটারসডব্লিউ

4
@ ফিলুসিয়াস কিউবজেক্টের ডেস্ট্রাক্টর ইতিমধ্যে ভার্চুয়াল, যা প্রতিটি সাবক্লাসের ডেস্ট্রাক্টরকে ভার্চুয়ালকে স্বয়ংক্রিয়ভাবে তৈরি করে।
রুবেনভবি

4
উত্তরাধিকার গাছের কোথাও যদি একটি শ্রেণীর ভার্চুয়াল ডেস্ট্রাক্টর থাকে তবে নীচের প্রতিটি শিশু শ্রেণীর ভার্চুয়াল ডেস্ট্রাক্টর থাকবে। এখন, যদি ভার্চুয়াল ডেস্ট্রাক্টর ছাড়াই এই জাতীয় ভার্চুয়াল ডেস্ট্রাক্টর চেইনের বাইরে কোনও পিতামাতার ক্লাস থাকে, তবে আমি বিশ্বাস করি যে আপনি যদি সেই নির্দিষ্ট বর্গের কোনও পয়েন্টার মুছে ফেলেন তবে সত্যিকারের বস্তুটি এই শৃঙ্খলে আরও কিছুটা নিচে থাকবে। কিউবজেক্টের শিশু শ্রেণির ক্ষেত্রে এবং সেই শিশু শ্রেণীর উদাহরণ হিসাবে কোনও কিউবজেক্ট পয়েন্টার মুছে ফেলার ক্ষেত্রে, কোনও সমস্যা নেই, এমনকি যদি আপনি সেই সাবক্লাসের ডেস্ট্রাক্টর ঘোষণায় ভার্চুয়াল কীওয়ার্ডটি ভুলে যান।
রুবেনভবি

47

আমি ডিউলস্কির জবাবটি প্রসারিত করে উল্লেখ করতে চাই যে Qt তে মালিকানার ধারণাটি খুব গুরুত্বপূর্ণ। ক্লাস এ যখন ক্লাস বি এর মালিকানা গ্রহণ করে, ক্লাস বি মুছে ফেলা হয় তখন ক্লাস বি মুছে ফেলা হয়। এমন অনেকগুলি পরিস্থিতি রয়েছে যেখানে আপনি যখন কোনও বস্তু তৈরি করেন এবং এর পিতামাতার নির্দিষ্ট করেন কেবল তখনই নয় যখন একটি বস্তু অন্যটির মালিক হয়।

এই ক্ষেত্রে:

QVBoxLayout* layout = new QVBoxLayout;
QPushButton someButton = new QPushButton; // No owner specified.
layout->addWidget(someButton); // someButton still has no owner.
QWidget* widget = new QWidget;
widget->setLayout(layout); // someButton is "re-parented".
                           // widget now owns someButton.

আরেকটি উদাহরণ:

QMainWindow* window = new QMainWindow;
QWidget* widget = new QWidget; //widget has no owner
window->setCentralWidget(widget); //widget is now owned by window.

সুতরাং, প্রায়শই ডকুমেন্টেশন চেক করুন, এটি সাধারণত নির্দিষ্ট করে যে কোনও পদ্ধতি কোনও জিনিসের মালিকানা প্রভাবিত করবে কিনা।

দেবিলেস্কি যেমন বলেছেন, এই বিধিগুলি কিউবজেক্ট থেকে প্রাপ্ত বস্তুর ক্ষেত্রে কেবলমাত্র প্রয়োগ হয়। যদি আপনার শ্রেণি কিউবজেক্ট থেকে উদ্ভূত না হয় তবে আপনাকে ধ্বংসটি নিজেই পরিচালনা করতে হবে।


লেখার মধ্যে পার্থক্য কী: QPushButton * someButton = new QPushButton (); বা কিউপুষবটন কিছুবাটন = নতুন কিউপুষবটন বা কেবল কিউপুশ বাটন কিছুবাটন;
মার্টিন

4
এহ, কিউপুশ বাটনের মধ্যে একটি বিরাট পার্থক্য রয়েছে * কিছু বুটন = নতুন কিউপুষবটন; এবং কিউপুষবটন কিছু বাটন;। প্রাক্তনটি বস্তুর গাদা উপর বরাদ্দ দেবে, তবে পরেরটি এটি স্ট্যাকের জন্য বরাদ্দ করবে। কিউপুশবাটন * কিছুবাটন = নতুন কিউপুষবটন () এর মধ্যে কোনও পার্থক্য নেই; এবং কিউপুষবটন কিছু বুটন = নতুন কিউপুষবটন;, তারা উভয়ই বস্তুর ডিফল্ট কনস্ট্রাক্টরকে কল করবে।
অস্টিন

আমি এটির জন্য খুব নতুন জিজ্ঞাসা করার জন্য দুঃখিত তবে "স্তূপের উপর বস্তু বরাদ্দ করুন" এবং "স্ট্যাকের উপর বরাদ্দ করুন" এর মধ্যে পার্থক্য কী? আমার কখন গাদা ব্যবহার করা উচিত এবং কখন আমার স্ট্যাক ব্যবহার করা উচিত? ধন্যবাদ!
মার্টিন

4
আপনার গতিশীল বরাদ্দ, অবজেক্ট স্কোপ এবং আরআইআই সম্পর্কে পড়তে হবে। প্লেইন সি ++ এর ক্ষেত্রে, যখনই সম্ভব সম্ভব আপনার স্ট্যাকের উপর অবজেক্টগুলি বরাদ্দ করা উচিত কারণ যখন সুযোগগুলি অদৃশ্য হয়ে যায় তখন বস্তুগুলি স্বয়ংক্রিয়ভাবে ধ্বংস হয়ে যায়। ক্লাসের সদস্যদের জন্য, পারফরম্যান্সের কারণে গাদা উপকরণগুলিকে বরাদ্দ করা ভাল। এবং আপনি যখনই কোনও ফাংশন / পদ্ধতির প্রয়োগকে "আউটলাইভ" করতে কোনও অবজেক্ট চান তখন আপনাকে সেই বস্তুটি গাদাতে বরাদ্দ করা উচিত। আবার এগুলি খুব গুরুত্বপূর্ণ বিষয় যা কিছু পাঠের প্রয়োজন।
অস্টিন

@ অস্টিন আপনার কর্মক্ষেত্রের জন্য স্তূপে শ্রেণীর সদস্যদের বরাদ্দ করার সাধারণ বিবৃতিটি হ'ল ষাঁড়। এটি সত্যই নির্ভর করে এবং আপনি পিউরফরম্যান্সে কোনও সমস্যা না পাওয়া পর্যন্ত স্বয়ংক্রিয় স্টোরেজ সময়কালের সাথে আপনার পরিবর্তনশীল পছন্দ করতে হবে prefer
রুবেনভবি

7

পিতামাতার (হয় কিউজেক্ট অবজেক্ট বা এর উদ্ভূত বর্গ) এর বাচ্চাদের পয়েন্টারের একটি তালিকা রয়েছে (কিউবজেক্ট / এটি প্রাপ্ত)। পিতামাতার ধ্বংস হওয়ার সময় পিতামাতারা তার সন্তানের তালিকার সমস্ত বস্তু মুছবেন। আপনি যখন বাবা-মাকে মুছে ফেলা হয় তখন শিশু কিশোর সামগ্রীটি স্বয়ংক্রিয়ভাবে মুছতে আপনি কিউবজেক্টের এই সম্পত্তিটি ব্যবহার করতে পারেন। নিম্নলিখিত কোড ব্যবহার করে সম্পর্ক স্থাপন করা যেতে পারে

QObject* parent = new QObject();
QObject* child = new QObject(parent);
delete parent;//all the child objects will get deleted when parent is deleted, child object which are deleted before the parent object is removed from the parent's child list so those destructor will not get called once again.

স্মার্টপয়েন্টার ব্যবহার করে কিউটিতে মেমরি পরিচালনা করার অন্যান্য উপায় রয়েছে। নিম্নলিখিত নিবন্ধ Qt বিভিন্ন স্মার্ট পয়েন্টার বর্ণনা। https://www.qt.io/blog/2009/08/25/count-with-me-how-many-smart-pointer-classes-does-qt-have


-2

এই উত্তরগুলিতে যোগ করার জন্য, স্পষ্টকরণের জন্য, আমি আপনাকে Visual Leak Detetorআপনার ভিজ্যুয়াল সি ++ প্রজেক্টের জন্য লাইব্রেরিটি সি ++ এর ভিত্তিতে অন্তর্ভুক্ত করার কারণে Qt প্রকল্পগুলি ব্যবহার করার পরামর্শ দিচ্ছি , এই লাইব্রেরিটি new, delete, free and mallocবিবৃতিগুলির সাথে সামঞ্জস্যপূর্ণ , এটি ভাল নথিভুক্ত এবং সহজেই ব্যবহারযোগ্য। ভুলে যাবেন না আপনি যখন নিজের QDialogবা QWidgetউত্তরাধিকার সূত্রে প্রাপ্ত ইন্টারফেস ক্লাস তৈরি করেন এবং তারপরে এই শ্রেণীর একটি নতুন অবজেক্ট তৈরি করেন, তখন setAttribute(Qt::WA_DeleteOnClose)আপনার অবজেক্টের ফাংশন কার্যকর করতে ভুলবেন না ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.