একটি স্বতন্ত্র shared_ptrউদাহরণের বিন্দুটি গ্যারান্টি দেওয়া (যতদূর সম্ভব) যে যতক্ষণ shared_ptrএটি সুযোগে থাকবে, এটি যে বস্তুটিকে নির্দেশ করে তা এখনও বিদ্যমান থাকবে, কারণ এর রেফারেন্স গণনা কমপক্ষে 1 হবে।
Class::only_work_with_sp(boost::shared_ptr<foo> sp)
{
// sp points to an object that cannot be destroyed during this function
}
সুতরাং একটি রেফারেন্স ব্যবহার করে shared_ptr, আপনি যে গ্যারান্টি অক্ষম। সুতরাং আপনার দ্বিতীয় ক্ষেত্রে:
Class::only_work_with_sp(boost::shared_ptr<foo> &sp) //Again, no copy here
{
...
sp->do_something();
...
}
আপনি কীভাবে জানবেন যে sp->do_something()নাল পয়েন্টারটির কারণে উড়ে যাবে না?
কোডের '' ... 'বিভাগগুলিতে কী আছে তা নির্ভর করে। আপনি যদি প্রথম '...' চলাকালীন কোনও কিছু কল করেন তবে তার shared_ptrএকই অজানাটিকে সাফ করার পার্শ্ব-প্রতিক্রিয়া (কোডের অন্য কোনও অংশে) রয়েছে ? এবং যদি এটি হয়ে ওঠে তবে কেবলমাত্র shared_ptrসেই অবজেক্টটির সাথে কেবল আলাদা করা যায়? বাই বাই অবজেক্ট, আপনি যেখানে চেষ্টা করতে এবং এটি ব্যবহার করতে চলেছেন ঠিক সেখানে।
সুতরাং এই প্রশ্নের উত্তর দেওয়ার দুটি উপায় রয়েছে:
আপনার পুরো প্রোগ্রামের উত্সটি খুব সাবধানে পরীক্ষা করুন যতক্ষণ না আপনি নিশ্চিত হন যে ফাংশন বডি চলাকালীন অবজেক্টটি মারা যাবে না।
পরামিতিটিকে পরিবর্তনের পরিবর্তে একটি রেফারেন্সের পরিবর্তে আলাদা স্বতন্ত্র বস্তুতে পরিণত করুন।
এখানে প্রযোজ্য সাধারণ বিট: কার্য সম্পাদনের জন্য আপনার কোডে ঝুঁকিপূর্ণ পরিবর্তনগুলি ঘটাবেন না যতক্ষণ না আপনি কোনও প্রোফাইকারের কাছে আপনার পণ্যকে বাস্তবসম্মত পরিস্থিতিতে সময় হিসাবে নির্ধারণ করেন এবং সিদ্ধান্ত হিসাবে পরিমাপ করেন যে আপনি যে পরিবর্তনটি করতে চান তা পরিবর্তন করে দেবে পারফরম্যান্সে উল্লেখযোগ্য পার্থক্য।
মন্তব্যকারী জিকিউ জন্য আপডেট
এখানে একটি স্বতন্ত্র উদাহরণ। এটি ইচ্ছাকৃতভাবে সহজ, তাই ভুলটি সুস্পষ্ট হবে। প্রকৃত উদাহরণগুলিতে, ভুলটি এতটা সুস্পষ্ট নয় কারণ এটি আসল বিবরণের স্তরগুলিতে লুকানো রয়েছে।
আমাদের একটি ফাংশন রয়েছে যা কোথাও একটি বার্তা প্রেরণ করবে। এটি একটি বৃহত্তর বার্তা হতে পারে তার পরিবর্তে std::stringএটি সম্ভবত একাধিক স্থানে পাস হওয়ার সাথে সাথে অনুলিপি করা হয় না, আমরা shared_ptrএকটি স্ট্রিং এ ব্যবহার করি :
void send_message(std::shared_ptr<std::string> msg)
{
std::cout << (*msg.get()) << std::endl;
}
(আমরা উদাহরণস্বরূপ এটি কনসোলে কেবল "প্রেরণ" করব)।
এখন আমরা আগের বার্তাটি মনে রাখার জন্য একটি সুবিধা যুক্ত করতে চাই। আমরা নিম্নলিখিত আচরণটি চাই: একটি চলক অবশ্যই উপস্থিত থাকতে হবে যাতে সর্বাধিক প্রেরিত বার্তা রয়েছে তবে বর্তমানে কোনও বার্তা প্রেরণ করার পরে কোনও পূর্ববর্তী বার্তা থাকতে হবে না (প্রেরণের আগে পরিবর্তনশীলটি পুনরায় সেট করা উচিত)। সুতরাং আমরা নতুন পরিবর্তনশীল ঘোষণা:
std::shared_ptr<std::string> previous_message;
তারপরে আমরা আমাদের নির্দিষ্ট করা বিধি অনুযায়ী আমাদের ফাংশনটি সংশোধন করি:
void send_message(std::shared_ptr<std::string> msg)
{
previous_message = 0;
std::cout << *msg << std::endl;
previous_message = msg;
}
সুতরাং, আমরা প্রেরণ শুরু করার আগে আমরা বর্তমানের পূর্ববর্তী বার্তাটি বাতিল করি এবং তারপরে পাঠানো শেষ হওয়ার পরে আমরা নতুন পূর্ববর্তী বার্তাটি সংরক্ষণ করতে পারি। সব ভালো. এখানে কিছু পরীক্ষার কোড দেওয়া হল:
send_message(std::shared_ptr<std::string>(new std::string("Hi")));
send_message(previous_message);
এবং যেমন প্রত্যাশা করা হয়েছে, এই Hi!দু'বার মুদ্রণ ।
এখন মিঃ মেনটেনিয়ার আসেন, যিনি কোডটি দেখেন এবং ভাবেন: আরে, সেই পরামিতিটি send_messageহ'ল shared_ptr:
void send_message(std::shared_ptr<std::string> msg)
স্পষ্টতই এটিকে পরিবর্তন করা যেতে পারে:
void send_message(const std::shared_ptr<std::string> &msg)
এই আনতে হবে কর্মক্ষমতা বৃদ্ধি চিন্তা করুন! (কিছু মনে করবেন না যে আমরা কয়েকটি চ্যানেলে সাধারণত একটি বৃহত্তর বার্তা প্রেরণ করতে চলেছি, সুতরাং পারফরম্যান্স বর্ধন অপ্রয়োজনীয় হিসাবে এত ছোট হবে)।
তবে আসল সমস্যাটি হ'ল এখন পরীক্ষার কোডটি অপরিবর্তিত আচরণের প্রদর্শন করবে (ভিজ্যুয়াল সি ++ 2010-এ ডিবাগ তৈরি করে, এটি ক্র্যাশ হয়ে যায়)।
মিঃ মেইনটেনার এতে অবাক, তবে send_messageসমস্যাটি ঘটতে থামাতে প্রয়াসে একটি প্রতিরক্ষামূলক চেক যোগ করেছেন :
void send_message(const std::shared_ptr<std::string> &msg)
{
if (msg == 0)
return;
তবে অবশ্যই এটি এখনও এগিয়ে যায় এবং ক্র্যাশ হয়, কারণ msgযখন send_messageডাকা হয় তখন কখনই শূন্য হয় না ।
আমি যেমন বলেছি, সমস্ত কোডের সাথে তুচ্ছ উদাহরণের সাথে একত্রে খুব কাছাকাছি থাকা, ভুলটি খুঁজে পাওয়া সহজ। কিন্তু চপল যে বস্তু একে অপরের সাথে পয়েন্টার রাখা মধ্যে আরো জটিল সম্পর্ক রিয়েল প্রোগ্রাম,, এটা করা সহজ করতে ভুল শনাক্ত করার জন্য প্রয়োজনীয় পরীক্ষার বিষয় গঠন করা ভুল, ও কঠোর।
সহজ সমাধান, যেখানে আপনি কোনও ক্রিয়াকলাপটি shared_ptrঅ-শূন্য জুড়ে চলার উপর নির্ভর করতে সক্ষম হতে চান তা হ'ল shared_ptrকার্যটির কোনও বিদ্যমানতার রেফারেন্সের উপর নির্ভর না করে তার নিজের সত্য বরাদ্দ করা shared_ptr।
নেতিবাচক দিকটি হ'ল অনুলিপি করা shared_ptrযায় না: এমনকি "লক-ফ্রি" বাস্তবায়নগুলি থ্রেডিং গ্যারান্টি সম্মানের জন্য একটি ইন্টারলকড অপারেশন ব্যবহার করতে হয়। সুতরাং পরিস্থিতিতে যেখানে একটি প্রোগ্রাম উল্লেখযোগ্যভাবে পরিবর্তন গতি আনে যাবে হতে পারে shared_ptrএকটি মধ্যে shared_ptr &। তবে এটি কোনও পরিবর্তন নয় যা নিরাপদে সমস্ত প্রোগ্রামে করা যায়। এটি প্রোগ্রামটির যৌক্তিক অর্থকে পরিবর্তন করে।
মনে রাখবেন যে আমরা যদি এর std::stringপরিবর্তে std::shared_ptr<std::string>এবং এর পরিবর্তে ব্যবহার করি তবে অনুরূপ বাগটি ঘটবে :
previous_message = 0;
বার্তা পরিষ্কার করতে, আমরা বলেছিলাম:
previous_message.clear();
তারপরে লক্ষণটি হ'ল দুর্ঘটনাক্রমে খালি বার্তা প্রেরণ করা হবে, পরিবর্তিত আচরণের পরিবর্তে। একটি খুব বড় স্ট্রিংয়ের অতিরিক্ত অনুলির ব্যয় কপি করার ব্যয়ের চেয়ে অনেক বেশি তাৎপর্যপূর্ণ হতে পারে shared_ptr, সুতরাং বাণিজ্য বন্ধ আলাদা হতে পারে।