স্মার্ট পয়েন্টার (বুস্ট) ব্যাখ্যা


220

নিম্নলিখিত পয়েন্টার সেট মধ্যে পার্থক্য কি? আপনি কখন প্রোডাকশন কোডে প্রতিটি পয়েন্টার ব্যবহার করবেন, যদি না হয়?

উদাহরণ প্রশংসা হবে!

  1. scoped_ptr

  2. shared_ptr

  3. weak_ptr

  4. intrusive_ptr

আপনি কি প্রোডাকশন কোডে বুস্ট ব্যবহার করেন?

উত্তর:


339

স্মার্ট পয়েন্টারগুলির মূল বৈশিষ্ট্য

আপনি যখন প্রতিটি স্মার্ট পয়েন্টার নির্ধারণ করতে পারেন এমন বৈশিষ্ট্যগুলি থাকে তখন এটি সহজ। তিনটি গুরুত্বপূর্ণ বৈশিষ্ট্য রয়েছে।

  • কোন মালিকানা
  • মালিকানা হস্তান্তর
  • মালিকানা ভাগ

প্রথমটির অর্থ হ'ল স্মার্ট পয়েন্টারটি বস্তুটি মুছতে পারে না, কারণ এটি তার নিজস্ব নয়। দ্বিতীয়টির অর্থ হল যে কেবলমাত্র একটি স্মার্ট পয়েন্টার একই সময় একই জিনিসকে নির্দেশ করতে পারে। যদি স্মার্ট পয়েন্টারটি ফাংশন থেকে ফিরে আসতে হয়, উদাহরণস্বরূপ, মালিকানা ফেরত স্মার্ট পয়েন্টারে স্থানান্তরিত হয়।

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

কিছু স্মার্ট পয়েন্টারগুলির মালিক দ্বিতীয় বা তৃতীয়টি সমর্থন করে না। সেহেতু তাদের ফাংশন থেকে ফেরত দেওয়া বা অন্য কোথাও পাস করা যাবে না। RAIIস্মার্ট পয়েন্টারটি স্থানীয় রাখার জন্য এবং যা স্রেফ তৈরি করা হয়েছে সেগুলির জন্য যা সবচেয়ে উপযুক্ত, তাই সুযোগের বাইরে চলে যাওয়ার পরে এটি কোনও জিনিসকে মুক্তি দেয়।

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

সি ++ 1 এক্স তথাকথিত "মুভ কনস্ট্রাক্টর" এবং "মুভ অ্যাসাইনমেন্ট অপারেটর" প্রবর্তন করে মালিকানা স্থানান্তর-এর জন্য স্থানীয় সমর্থন সরবরাহ করে। এটি এমন একটি স্থানান্তর-মালিকানার স্মার্ট পয়েন্টার সহ আসে unique_ptr

শ্রেণীবদ্ধ স্মার্ট পয়েন্টার

scoped_ptrহ'ল একটি স্মার্ট পয়েন্টার যা না বদলযোগ্য বা শেরেও যায় না। আপনার যদি স্থানীয়ভাবে মেমরি বরাদ্দ করা দরকার তবে এটি কেবল ব্যবহারযোগ্য, তবে নিশ্চিত হন যে সুযোগের বাইরে চলে গেলে এটি আবার মুক্তি পেয়েছে। আপনি যদি এটি করতে চান তবে এটি এখনও অন্য একটি স্কোপযুক্ত_প্টারের সাথে সরিয়ে নেওয়া যেতে পারে।

shared_ptrহ'ল একটি স্মার্ট পয়েন্টার যা মালিকানা ভাগ করে দেয় (উপরে তৃতীয় ধরণের)। এটি রেফারেন্স গণনা করা হয় যাতে এটির শেষ কপিটি সুযোগের বাইরে চলে যায় এবং তারপরে এটি পরিচালিত অবজেক্টটিকে মুক্তি দেয় see

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

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

unique_ptrমালিকানা পয়েন্টার স্থানান্তর হয়। আপনি এটি অনুলিপি করতে পারবেন না, তবে আপনি C ++ 1x এর মুভ কনস্ট্রাক্টর ব্যবহার করে এটিকে সরাতে পারেন:

unique_ptr<type> p(new type);
unique_ptr<type> q(p); // not legal!
unique_ptr<type> r(move(p)); // legal. p is now empty, but r owns the object
unique_ptr<type> s(function_returning_a_unique_ptr()); // legal!

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


3
প্রশংসা বন্ধু জন্য ধন্যবাদ। আমি এটির প্রশংসা করি তাই আপনি এখন আরও +1 পেতে চলেছেন: পি
জোহানেস স্কাউব - লিটব

@ লিটব: "মালিকানা হস্তান্তর" সম্পর্কে আমার সন্দেহ আছে; আমি সম্মত হই যে সি ++ 03 তে অবজেক্টগুলির মধ্যে মালিকানার কোনও প্রকৃত স্থানান্তর নেই , তবে স্মার্ট পয়েন্টারগুলির জন্য এটি করা যায় না, এখানে বর্ণিত ধ্বংসাত্মক অনুলিপি প্রক্রিয়া দ্বারা informit.com/articles/article.aspx?p=31529&seqNum= ৫
কিংবদন্তি 2 কে

3
চমত্কার উত্তর। দ্রষ্টব্য: auto_ptrইতিমধ্যে অবহিত করা হয়েছে (সি ++ 11)।
নিকোলে

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

আমি আরও বলা হয়েছে যে আরও ভাল ক্যাশে সংহতি জন্য intrusive_ptrপছন্দনীয় হতে পারে shared_ptr। দৃশ্যত ক্যাশে আরও ভাল সঞ্চালন করে যদি আপনি পৃথক বস্তুর পরিবর্তে পরিচালিত অবজেক্টের মেমরির অংশ হিসাবে রেফারেন্স গণনাটি সঞ্চয় করেন। এটি পরিচালিত অবজেক্টের একটি টেম্পলেট বা সুপারক্লাসে প্রয়োগ করা যেতে পারে।
এলিয়ট

91

scoped_ptr সবচেয়ে সহজ। যখন এটি সুযোগের বাইরে চলে যায় তখন এটি ধ্বংস হয়ে যায়। নিম্নলিখিত কোডটি অবৈধ (স্কোপযুক্ত_প্টারগুলি অনুলিপিযোগ্য) তবে একটি বিষয়টি ব্যাখ্যা করবে:

std::vector< scoped_ptr<T> > tPtrVec;
{
     scoped_ptr<T> tPtr(new T());
     tPtrVec.push_back(tPtr);
     // raw T* is freed
}
tPtrVec[0]->DoSomething(); // accessing freed memory

শেয়ারড_পিটার হল রেফারেন্স গণনা করা হয়। প্রতিবার কোনও অনুলিপি বা অ্যাসাইনমেন্ট ঘটে, রেফারেন্স গণনাটি বাড়ানো হয়। প্রতিবার কোনও উদাহরণের ধ্বংসকারীকে বরখাস্ত করার সময়, কাঁচা টি * এর জন্য রেফারেন্স গণনা হ্রাস করা হয়। এটি একবার 0 হলে, পয়েন্টারটি মুক্ত হয়।

std::vector< shared_ptr<T> > tPtrVec;
{
     shared_ptr<T> tPtr(new T());
     // This copy to tPtrVec.push_back and ultimately to the vector storage
     // causes the reference count to go from 1->2
     tPtrVec.push_back(tPtr);
     // num references to T goes from 2->1 on the destruction of tPtr
}
tPtrVec[0]->DoSomething(); // raw T* still exists, so this is safe

দুর্বল_সিপিআর একটি ভাগ করা পয়েন্টারটির একটি দুর্বল রেফারেন্স যা আপনাকে পয়েন্ট-টু ভাগ করা_পিটারটি এখনও রয়েছে কিনা তা পরীক্ষা করে দেখার প্রয়োজন

std::vector< weak_ptr<T> > tPtrVec;
{
     shared_ptr<T> tPtr(new T());
     tPtrVec.push_back(tPtr);
     // num references to T goes from 1->0
}
shared_ptr<T> tPtrAccessed =  tPtrVec[0].lock();
if (tPtrAccessed[0].get() == 0)
{
     cout << "Raw T* was freed, can't access it"
}
else
{
     tPtrVec[0]->DoSomething(); // raw 
}

intrusive_ptr সাধারণত ব্যবহৃত যখন একটি 3rd পার্টি স্মার্ট খুঁজছেন এরকম আপনি ব্যবহার করা আবশ্যক হয়। এটি রেফারেন্স গণনা যোগ করতে এবং হ্রাস করার জন্য একটি ফ্রি ফাংশন কল করবে more আরও তথ্যের জন্য ডকুমেন্টেশন বৃদ্ধির জন্য লিঙ্কটি দেখুন।


নয if (tPtrAccessed[0].get() == 0)হতে অনুমান if (tPtrAccessed.get() == 0) ?
রাজেশ্বর

@DougT। আপনি কি বিশ্বাস করেন যে জাভা রেফারেন্স সহ একই ধারণা ব্যবহার করে? নরম, শক্ত, দুর্বল ইত্যাদি?
গানসুব

20

boost::ptr_containerস্মার্ট পয়েন্টার বাড়ানোর কোনও সমীক্ষায় উপেক্ষা করবেন না । এগুলি এমন পরিস্থিতিতে অমূল্য হতে পারে যেখানে উদাহরণ std::vector<boost::shared_ptr<T> >খুব ধীর হয়।


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

12

আমি ডকুমেন্টেশন তাকান সম্পর্কে পরামর্শ দ্বিতীয়। এটি যতটা ভয়ঙ্কর মনে হয় তেমনটি নয়। এবং কয়েকটি সংক্ষিপ্ত ইঙ্গিত:

  • scoped_ptr- কোনও পয়েন্টার যখন সুযোগের বাইরে চলে যায় তখন স্বয়ংক্রিয়ভাবে মোছা হয়। দ্রষ্টব্য - কোনও অ্যাসাইনমেন্ট সম্ভব নয়, তবে কোনও ওভারহেডের পরিচয় নেই
  • intrusive_ptr- কোনও ওভারহেড ছাড়াই রেফারেন্স গণনা পয়েন্টার smart_ptr। তবে বস্তু নিজেই রেফারেন্স গণনা সঞ্চয় করে
  • weak_ptr- shared_ptrবিজ্ঞপ্তি নির্ভরতা (ডকুমেন্টেশন পড়ুন, এবং সুন্দর ছবির জন্য গুগলে অনুসন্ধান করুন) এর ফলে পরিস্থিতি মোকাবেলায় একসাথে কাজ করে ;
  • shared_ptr - স্মার্ট পয়েন্টারগুলির জেনেরিক, সর্বাধিক শক্তিশালী (এবং হেভিওয়েট) (উত্সাহ দেওয়া অফারগুলি থেকে)
  • এছাড়াও পুরানো রয়েছে auto_ptr, এটি নিশ্চিত করে যে নিয়ন্ত্রণটি কোনও সুযোগ ছাড়লে এটি যে বিষয়টিকে নির্দেশ করে তা স্বয়ংক্রিয়ভাবে ধ্বংস হয়ে যায়। তবে এর অন্যান্য ছেলের চেয়ে আলাদা কপির শব্দার্থবিজ্ঞান রয়েছে।
  • unique_ptr- সি ++ 0x নিয়ে আসবে

সম্পাদনার প্রতিক্রিয়া: হ্যাঁ


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