std :: শেয়ারড_পিটার একটি শেষ অবলম্বন হিসাবে?


59

আমি কেবল "চলমান নেটিভ ২০১২" স্ট্রিমগুলি দেখছিলাম এবং আমি সে সম্পর্কে আলোচনাটি লক্ষ্য করেছি std::shared_ptr। বার্জারের কিছুটা নেতিবাচক দৃষ্টিভঙ্গি std::shared_ptrএবং তাঁর মন্তব্য শুনে আমি কিছুটা অবাক হয়েছিলাম এবং কোনও মন্তব্য যখন কোনও বস্তুর জীবনকাল অনিশ্চিত হয় তখন এটি "শেষ অবলম্বন" হিসাবে ব্যবহার করা উচিত (যা আমি বিশ্বাস করি, তাঁর মতে, ঘটনাটি ঘটতে হবে না)।

কেউ কি আরও কিছু গভীরতার সাথে এটি ব্যাখ্যা করতে যত্ন নিতে হবে? আমরা কীভাবে নিরাপদ উপায়ে std::shared_ptrলাইফ-টাইম অবজেক্ট এবং পরিচালনা করতে পারি ?


8
পয়েন্টার ব্যবহার করছেন না? বস্তুর স্বতন্ত্র মালিক থাকা, যা আজীবন পরিচালনা করে?
বো পারসন

2
সুস্পষ্টভাবে শেয়ার করা ডেটা সম্পর্কে কী? পয়েন্টার ব্যবহার না করা শক্ত। এছাড়াও স্টাড :: শেয়ার্ড_পয়েন্টার সেই ক্ষেত্রে নোংরা "আজীবন পরিচালনা" করবে
কামিল ক্লিমেক

6
আপনি কি উপস্থাপিত পরামর্শকে কম শুনার এবং সেই পরামর্শের পিছনে যুক্তির দিকে আরও বিবেচনা করেছেন? এই পদ্ধতিতে এই ধরণের পরামর্শ কার্যকর হতে পারে সে সম্পর্কে তিনি খুব সুন্দরভাবে ব্যাখ্যা করেছেন।
নিকল বোলাস

@ নিকলবোলাস: আমি পরামর্শ এবং যুক্তি শুনেছিলাম তবে স্পষ্টতই আমি বুঝতে পারি নি যে আমি এটি যথেষ্টভাবে বুঝতে পেরেছি।
রোন্যাগ

কোন সময় তিনি "শেষ অবলম্বন" বলেন? ( চ্যানেল 9.msdn.com/Events/GoingNative/GoingNative-2012/… ) এ 36 মিনিটে বিটটি দেখছেন তিনি বলেছেন যে তিনি পয়েন্টারগুলির ব্যবহার সম্পর্কে সতর্ক রয়েছেন, তবে তিনি সাধারণভাবে পয়েন্টারগুলি বোঝাতে চেয়েছেন, কেবল শেয়ারড_প্টর এবং ইউনিক_পিটার নয়, এমনকি ' নিয়মিত 'পয়েন্টার। তিনি বোঝাচ্ছেন যে বস্তুগুলিকে নিজেরাই (এবং নতুন দিয়ে বরাদ্দ করা সামগ্রীর দিকে নির্দেশক নয়) পছন্দ করা উচিত। আপনি উপস্থাপনাটি পরে কি ভাবছিলেন?
ফারাপ

উত্তর:


55

আপনি যদি ভাগ করা মালিকানা এড়াতে পারেন তবে আপনার অ্যাপ্লিকেশনটি সহজ এবং সহজতর বোঝা হবে এবং তাই রক্ষণাবেক্ষণের সময় বাগগুলিতে কম সংবেদনশীল। জটিল বা অস্পষ্ট মালিকানার মডেলগুলি ভাগ করে নেওয়া রাষ্ট্রের মাধ্যমে আবেদনের বিভিন্ন অংশের কাপলিংগুলি অনুসরণ করতে অসুবিধা দেখা দেয় যা সহজে ট্র্যাকযোগ্য হয় না।

এটি দেওয়া, স্বয়ংক্রিয় স্টোরেজ সময়কাল সহ অবজেক্টগুলি ব্যবহার করা এবং "মান" উপ-অবজেক্টগুলি থাকা ভাল। এটি ব্যর্থ হওয়া, unique_ptrএটি একটি সেরা বিকল্প হতে পারে shared_ptr- যদি শেষ অবলম্বন না হয় - কিছু উপায়ে পছন্দসই সরঞ্জামগুলির তালিকা থেকে যায়।


5
আউট poiting যে সমস্যা টেকনো নিজেই (ভাগ মালিকানা), কিন্তু অসুবিধা এটির জন্য প্রবর্তন নয় জন্য +1 আমাদের নিছক মানুষের কে পাঠোদ্ধার কি হচ্ছে না।
ম্যাথিউ এম।

যাইহোক, এই জাতীয় দৃষ্টিভঙ্গি গ্রহণ করা বেশিরভাগ অ-তুচ্ছ ওওপি ক্লাসগুলিতে (অনুলিপিযোগ্যতার কারণে।
রওয়ং

48

উন্নত মেয়াদের অভাবে বর্জন যে পৃথিবীতে বাস করেন তা হ'ল ... একাডেমিক। যদি আপনার কোডটি এমনভাবে ডিজাইন ও কাঠামোযুক্ত করা যায় যে অবজেক্টগুলিতে খুব ইচ্ছাকৃতভাবে সম্পর্কিত সম্পর্কিত শ্রেণিবিন্যাস রয়েছে, যেমন মালিকানার সম্পর্কগুলি কঠোর এবং অবারিত হয়, কোড এক দিকে প্রবাহিত হয় (উচ্চ-স্তর থেকে নিম্ন-স্তরে) এবং অবজেক্টগুলি কেবল নিম্নের সাথে কথা বলে অনুক্রমের, তাহলে আপনি অনেক প্রয়োজন পাবে না shared_ptr। এটি এমন কিছু যা আপনি বিরল ইভেন্টগুলিতে ব্যবহার করেন যেখানে কাউকে নিয়ম ভঙ্গ করতে হয়। তবে অন্যথায়, আপনি কেবলমাত্র vectors বা অন্যান্য ডেটা স্ট্রাকচারের সমস্ত কিছুকে স্ট্যান্ড করতে পারেন যা মান শব্দার্থক ব্যবহার করে, এবং যেগুলি unique_ptrআপনাকে এককভাবে বরাদ্দ করতে হবে তার জন্য।

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

এই জাতীয় সিস্টেমে নগ্ন পয়েন্টার ধরে রাখা ... ঠিক বিপজ্জনক নয়, তবে এটি প্রশ্ন উত্থাপন করে। দুর্দান্ত জিনিসটি shared_ptrহ'ল এটি বস্তুর আজীবন সম্পর্কে যুক্তিসঙ্গত গ্যারান্টি সরবরাহ করে। এটা কি ভাঙ্গা যায়? অবশ্যই. কিন্তু মানুষ const_castজিনিসগুলিও করতে পারে; বুনিয়াদি যত্ন এবং খাওয়ানো হ'ল shared_ptrবরাদ্দ করা সামগ্রীর মালিকানা অবশ্যই ভাগ করে নেওয়া উচিত for

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

যেহেতু সত্যিকারের সিস্টেমে এই অনমনীয়তা অর্জন করা সবসময় সম্ভব নয়, তাই আপনার আজীবন নিশ্চিত করার জন্য আপনার কিছু উপায় প্রয়োজন । কখনও কখনও, আপনার সম্পূর্ণ মালিকানার প্রয়োজন হয় না; কখনও কখনও, আপনাকে কেবল পয়েন্টারটি কখন খারাপ বা ভাল তা জানার দরকার হয়। এটিই সেখানে weak_ptrআসে There এমন ঘটনাও ঘটেছে যেখানে আমি একটি ব্যবহার করতে পারি unique_ptrবা boost::scoped_ptrকরতে পারি, তবে আমাকে একটি ব্যবহার করতে হয়েছিল shared_ptrকারণ আমার বিশেষত কাউকে "অস্থির" পয়েন্টার দেওয়ার দরকার ছিল। একজন পয়েন্টার যাঁর আজীবন অনির্দিষ্ট ছিল এবং তারা যখন জিজ্ঞাসা করতে পারে যে কখন সেই পয়েন্টারটি ধ্বংস হয়েছিল।

বিশ্বের অবস্থা যখন নির্বিঘ্ন থাকে তখন বেঁচে থাকার নিরাপদ উপায়।

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

এখন, অর্থাৎ যে না shared_ptrহতে পারে না overused ; এটা অবশ্যই পারে। বিশেষত unique_ptrপূর্ববর্তী, অনেকগুলি ক্ষেত্রেই আমি কেবলমাত্র ব্যবহার boost::shared_ptrকরেছি কারণ আমার চারপাশে একটি আরআইআই পয়েন্টারটি পাস করার বা এটি একটি তালিকায় রাখা দরকার ছিল। পদক্ষেপ শব্দার্থবিদ্যা ছাড়া এবং unique_ptr, boost::shared_ptrশুধুমাত্র বাস্তব সমাধান ছিল।

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


4
+1: উদাহরণস্বরূপ বুস্ট :: asio দেখুন। আমি মনে করি ধারণাটি অনেকগুলি অঞ্চলে প্রসারিত হয়েছে, আপনি কখনই সংকলন করতে পারেন তা জানতে পারবেন না কোন ইউআই উইজেট বা অ্যাসিঙ্ক্রোনাস কলটি কোনও বস্তুকে ত্যাগ করার জন্য সর্বশেষ, এবং শেয়ারড_পিটারের সাথে আপনার জানা দরকার নেই । এটি স্পষ্টতই প্রতিটি পরিস্থিতিতে প্রয়োগ হয় না , টুল-বাক্সে আরও একটি (খুব দরকারী) সরঞ্জাম।
গাই স্যারটন

3
কিছুটা দেরিতে মন্তব্য; shared_ptrএমন সিস্টেমগুলির জন্য দুর্দান্ত যেখানে সি ++ পাইথনের মতো স্ক্রিপ্টিং ভাষার সাথে সংহত করে। ব্যবহার করে boost::python, সি ++ এবং পাইথন পার্শ্বে রেফারেন্স গণনা ব্যাপকভাবে সহযোগিতা করে; সি ++ থেকে পাওয়া যে কোনও বস্তু এখনও অজগরতে রাখা যেতে পারে এবং এটি মারা যায় না।
eudoxos

1
কেবলমাত্র রেফারেন্সের জন্য আমার বোঝার জন্য ওয়েবকিট বা ক্রোমিয়াম ব্যবহার নয় shared_ptr। উভয়ই তাদের নিজস্ব বাস্তবায়ন ব্যবহার করে intrusive_ptr। আমি কেবল
এটিই এনেছি

1
@gman: আপনার মন্তব্যটি আমি খুব বিভ্রান্তিকর বলে মনে করি, যেহেতু স্ট্রোস্ট্রপের আপত্তি সম্পর্কে shared_ptrসমানভাবে প্রযোজ্য intrusive_ptr: তিনি ধারণার কোনও নির্দিষ্ট বানানকে নয়, অংশীদারি মালিকানার পুরো ধারণাটি নিয়ে আপত্তি করছেন। তাই এই প্রশ্ন উদ্দেশ্যে, যারা বড় অ্যাপ্লিকেশন দুটি বাস্তব জগতের উদাহরণ না ব্যবহার shared_ptr। (এবং আরও কী, তারা প্রমাণ করে যে shared_ptrএটি সক্ষম না হওয়া সত্ত্বেও এটি কার্যকর weak_ptr))
রুখ

1
এফডব্লিউআইডাব্লিউ, দাবিটি মোকাবিলার জন্য যে বর্জন একাডেমিক বিশ্বে বাস করছেন: আমার সমস্ত খাঁটি শিল্পজীবনে (যার মধ্যে জি -২০ স্টক এক্সচেঞ্জের সহ-স্থাপত্য এবং একমাত্র 500 কে-প্লেয়ার এমওজি আর্কিটেকচার অন্তর্ভুক্ত) আমি যখন কেবল সত্যই প্রয়োজন তখন আমি কেবল 3 টি ঘটনা দেখেছি অংশিদারী মালিকানা. আমি এখানে 200% বজ্রেনের সাথে আছি।
নো-বাগস হরে

37

আমি বিশ্বাস করি না যে আমি কখনও ব্যবহার করেছি std::shared_ptr

বেশিরভাগ সময়, কোনও বস্তু কোনও না কোনও সংগ্রহের সাথে সম্পর্কিত হয়, যা এটি তার পুরো জীবনকালের জন্য অন্তর্ভুক্ত। এক্ষেত্রে আপনি কেবল ব্যবহার করতে পারেন whatever_collection<o_type>বা whatever_collection<std::unique_ptr<o_type>>, সেই সংগ্রহটি কোনও বস্তুর সদস্য বা একটি স্বয়ংক্রিয় ভেরিয়েবল being অবশ্যই, যদি আপনার গতিশীল সংখ্যক অবজেক্টের প্রয়োজন না হয় তবে আপনি কেবল স্থির আকারের একটি স্বয়ংক্রিয় অ্যারে ব্যবহার করতে পারেন।

সংগ্রহের মাধ্যমে পুনরাবৃত্তি বা অবজেক্টের অন্য কোনও ক্রিয়াকলাপের মালিকানা ভাগ করতে কোনও সহায়ক ফাংশনের প্রয়োজন নেই ... এটি বস্তুটি ব্যবহার করে, তারপরে ফিরে আসে এবং কলার গ্যারান্টি দেয় যে পুরো কলের জন্য অবজেক্টটি বেঁচে থাকবে । এটি এখন পর্যন্ত কলার এবং কলির মধ্যে সর্বাধিক ব্যবহৃত চুক্তি।


নিকল বোলাস মন্তব্য করেছিলেন যে "যদি কোনও বস্তু একটি নগ্ন পয়েন্টার ধরে রাখে এবং সেই বস্তুটি মারা যায় ... ওফ!" এবং "অবজেক্টগুলিকে অবশ্যই সেই জিনিসটির সেই জীবনযাত্রার মধ্য দিয়ে জীবনযাপন করা উচিত তা নিশ্চিত করা দরকার Only কেবল এটিই shared_ptrসম্ভব।"

আমি এই যুক্তি কিনছি না। অন্তত shared_ptrএই সমস্যাটি সমাধান করে না । কি সম্পর্কে:

  • কিছু হ্যাশ টেবিল যদি কোনও বস্তুর উপরে ধারণ করে এবং সেই বস্তুর হ্যাশকোড পরিবর্তন হয় ... ওফস।
  • যদি কিছু ফাংশন কোনও ভেক্টরকে পুনরাবৃত্তি করে এবং সেই উপাদানটিতে একটি উপাদান intoোকানো হয় ... ওফস।

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

অবজেক্টস "মরে" না, কিছু কোডের টুকরা সেগুলি নষ্ট করে দেয়। এবং shared_ptrকল কন্ট্রাক্টটি বের করার পরিবর্তে সমস্যাটি ছুঁড়ে ফেলা একটি মিথ্যা সুরক্ষা।


17
@ লোনাগ: আমার সন্দেহ হয় যে আপনি এটি ব্যবহার শুরু করেছেন যেখানে কাঁচা পয়েন্টারটি আরও ভাল হত, কারণ "কাঁচা পয়েন্টারগুলি খারাপ"। তবে কাঁচা পয়েন্টারগুলি খারাপ নয় । কেবল কোনও কাঁচা পয়েন্টারটির সাথে প্রথম, মালিকের পয়েন্টার তৈরি করা খারাপ, কারণ তারপরে আপনাকে ম্যানুয়ালি মেমোরি পরিচালনা করতে হবে, যা ব্যতিক্রমগুলির উপস্থিতিতে অ-তুচ্ছ। তবে হ্যান্ডেল বা পুনরুক্তি হিসাবে কাঁচা পয়েন্টার ব্যবহার করা ঠিক আছে।
বেন ভয়েগট

4
@ বেনভয়েগ্ট: অবশ্যই, নগ্ন পয়েন্টারগুলির চারপাশে যাওয়ার সমস্যাটি হ'ল আপনি অবজেক্টের জীবনকাল জানেন না। যদি কিছু বস্তু একটি নগ্ন পয়েন্টার ধরে রাখে এবং সেই বস্তুটি মারা যায় ... ওফ। ঠিক এ জাতীয় জিনিস shared_ptrএবং weak_ptrএড়ানোর জন্য ডিজাইন করা হয়েছিল were বাজর্ন একটি বিশ্বে বাঁচার চেষ্টা করে সবকিছুই ছিল একটি সুন্দর, সুস্পষ্ট জীবনকাল এবং তার চারপাশে সবকিছুই নির্মিত। এবং আপনি যদি এই বিশ্ব গড়তে পারেন, দুর্দান্ত। কিন্তু আসল বিশ্বে এটি এমনটা নয়। অবজেক্টস নিশ্চিত করা প্রয়োজন যে বস্তুটি সেই বস্তুর জীবন যাপন করে। কেবল এটিই shared_ptrকরতে পারে।
নিকোল বোলাস

5
@ নিকোলবোলাস: এটি মিথ্যা সুরক্ষা। যদি কোনও ফাংশনের কলার স্বাভাবিক গ্যারান্টি সরবরাহ না করে: "ফাংশন কল করার সময় এই বিষয়টিকে বাইরের কোনও পক্ষের দ্বারা স্পর্শ করা হবে না" তবে উভয় ক্ষেত্রেই বাহ্যিক পরিবর্তনগুলি কীভাবে অনুমোদিত তা নিয়ে একমত হওয়া দরকার। shared_ptrকেবলমাত্র একটি নির্দিষ্ট বাইরের পরিবর্তনকে প্রশমিত করে, এমনকি সর্বাধিক সাধারণও নয়। এবং যদি ফাংশন কল চুক্তি অন্যথায় নির্দিষ্ট করে তবে তার জীবদ্দশায় সঠিক কিনা তা নিশ্চিত করা অবজেক্টের দায়িত্ব নয়।
বেন ভয়েগট

6
@ নিকলবোলাস: যদি কোনও ফাংশন কোনও অবজেক্ট তৈরি করে এবং পয়েন্টারের মাধ্যমে এটি ফিরিয়ে দেয় তবে এটি একটি হওয়া উচিত, এটি unique_ptrপ্রকাশ করে যে বস্তুর কাছে কেবল একটি পয়েন্টার রয়েছে এবং এর মালিকানা রয়েছে।
বেন ভয়েগট

6
@ নিকল: যদি এটি কোনও সংগ্রহের মধ্যে কোনও পয়েন্টার সন্ধান করে, তবে সংগ্রহের মধ্যে পয়েন্টার ধরণের যা আছে তা বা সংগ্রহের মান রয়েছে তবে কোনও কাঁচা পয়েন্টার ব্যবহার করা উচিত। যদি এটি একটি অবজেক্ট তৈরি করে এবং কলার একটি চায় shared_ptr, তবে এটি এখনও ফিরে আসা উচিত unique_ptr। থেকে রূপান্তর unique_ptrকরতে shared_ptrসহজ হয়, কিন্তু বিপরীত যুক্তি অসম্ভব।
বেন ভয়েগট

16

আমি নিখুঁত পদগুলিতে ("শেষ অবলম্বন" এর মতো) না ভাবলেও সমস্যা ডোমেনের সাথে তুলনামূলক পছন্দ করি।

সি ++ আজীবন পরিচালনা করার জন্য বিভিন্ন উপায়ে অফার করতে পারে। তাদের মধ্যে কিছু স্ট্যাক চালিত উপায়ে পুনরায় কন্ডোস করার চেষ্টা করে। অন্য কেউ কেউ এই সীমাবদ্ধতা থেকে বাঁচার চেষ্টা করেন। এর মধ্যে কিছু "আক্ষরিক", অন্যরা প্রায় অনুমান।

আসলে আপনি পারবেন:

  1. খাঁটি মান শব্দার্থক ব্যবহার করুন । অপেক্ষাকৃত ছোট বস্তু যেখানে কি গুরুত্বপূর্ণ "মান" এবং "পরিচয়" হয়, যেখানে আপনি দুই অনুমান করতে পারেন জন্য কাজ করে Personএকটি একই থাকার nameএকই ব্যক্তি (: দুই একটি একই প্রতিনিধিত্ব ভাল ব্যক্তি )। লাইফটাইম মেশিন স্ট্যাকের দ্বারা মঞ্জুর করা হয়, শেষের দিকে - প্রোগ্রামটির থেকে কোনও फरक হয় না (যেহেতু কোনও ব্যক্তি এটির নাম , Personএটি যা বহন করে তা বিবেচনা করে না)
  2. বরাদ্দকৃত বস্তু এবং সম্পর্কিত রেফারেন্স বা পয়েন্টারগুলি স্ট্যাক ব্যবহার করুন : বহুকর্মকে অনুমতি দেয় এবং আজীবন অবজেক্টকে মঞ্জুরি দেয়। "স্মার্ট পয়েন্টার" এর প্রয়োজন নেই, যেহেতু আপনি নিশ্চিত করেন যে কোনও বস্তু কাঠামোগুলি দ্বারা "পয়েন্ট" করা যায় না যা স্ট্যাকের মধ্যে যে বস্তুটি তারা দেখায় তার চেয়ে বেশি দীর্ঘ হয় (প্রথমে বস্তুটি তৈরি করে, তারপরে কাঠামোগুলি যেগুলি উল্লেখ করে)।
  3. স্ট্যাক পরিচালিত হিপ বরাদ্দকৃত বস্তুগুলি ব্যবহার করুন : এটিই স্টডি :: ভেক্টর এবং সমস্ত ধারকগুলি std::unique_ptrকরেন এবং ওয়াট করেন (আপনি এটি আকার 1 এর ভেক্টর হিসাবে ভাবতে পারেন)। আবার, আপনি স্বীকার করেন যে তারা যে ডেটা স্ট্রাকচারের উল্লেখ করেছেন তার (পরে) পূর্বে অবজেক্টটি উপস্থিত হতে শুরু করে (এবং তাদের অস্তিত্ব শেষ করে)।

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

  • অবজেক্ট পরিচালনা এবং সম্পর্কিত উল্লেখ কাঠামো পরিচালনা সম্পর্কে কিছু শৃঙ্খলা প্রবর্তন করুন বা ...
  • "খাঁটি স্ট্যাক ভিত্তিক জীবদ্দশায় বেঁচে থাকুন" এর অন্ধকার দিকে যান: অবজেক্টকে অবশ্যই তাদের তৈরি করা ফাংশনগুলি থেকে স্বাধীনভাবে চলে যেতে হবে। এবং অবশ্যই তাদের চলে যাওয়া উচিত ... যতক্ষণ না তাদের প্রয়োজন হয়

সি ++ আইস্টেলসফের সেই ইভেন্টটি নিরীক্ষণের জন্য কোনও নেটিভ মেকানিজম নেই ( while(are_they_needed)), সুতরাং আপনার সাথে আনুমানিক আনতে হবে:

  1. ভাগ করা মালিকানা ব্যবহার করুন : অবজেক্টস লাইফ একটি "রেফারেন্স কাউন্টার" -এ আবদ্ধ: যদি "মালিকানা" স্তরক্রমিকভাবে সংগঠিত করা যায়, ব্যর্থ হয় যেখানে মালিকানা লুপের অস্তিত্ব থাকতে পারে works এটিই স্ট্যান্ড :: শেয়ারড_পিটার করে। এবং দুর্বল_পিটার লুপটি ভাঙ্গতে ব্যবহার করা যেতে পারে। এটি বেশিরভাগ সময় কাজ করে তবে বৃহত ডিজাইনে ব্যর্থ হয়, যেখানে অনেক ডিজাইনার বিভিন্ন দলে কাজ করেন এবং কারা নিশ্চয়ই তার মালিক (এ সম্পর্কিত উদাহরণটি দ্বৈত পছন্দ হওয়া শৃঙ্খলার উদাহরণ) এর কোনও স্পষ্ট কারণ নেই (কিছুটা প্রয়োজন থেকে কিছু আসছে something পূর্ববর্তী পরবর্তীটি পূর্ববর্তী উল্লেখ করা বা পরবর্তীটির পরবর্তীটির উল্লেখ করার পরে? পরবর্তী কোনও প্রয়োজনের অনুপস্থিতিতে থো সলিউশন সমতুল্য, এবং বড় প্রকল্পে আপনি সেগুলি মিশ্রিত করার ঝুঁকি নিয়েছেন)
  2. আবর্জনা সংগ্রহের জঞ্জাল ব্যবহার করুন : আপনি কেবল আজীবন বাধা দেবেন না। আপনি কালেক্টরকে সময়ে সময়ে চালনা করেন এবং যা না করা হয় তাকে "আর প্রয়োজন হয় না" এবং ... ভাল ... আহেম ... ধ্বংস করা হয়? চূড়ান্ত? হিমায়িত ?. এখানে বেশ কয়েক জন জিসি সংগ্রাহক রয়েছেন, তবে আমি সত্যিই সি ++ সচেতন এমন কোনও খুঁজে পাই না। তাদের মধ্যে বেশিরভাগ বিনামূল্যে মেমরি, অবজেক্ট ধ্বংস সম্পর্কে যত্নশীল নয়।
  3. সঠিক মানক পদ্ধতিগুলির ইন্টারফেস সহ একটি সি ++ সচেতন আবর্জনা সংগ্রহকারী ব্যবহার করুন। এটি সন্ধান করার জন্য শুভকামনা।

শেষের একদম প্রথম সমাধানে গিয়ে অবজেক্টের আজীবন বৃদ্ধি পরিচালনার জন্য প্রয়োজনীয় সহায়ক ডেটা স্ট্রাকচারের পরিমাণ, কারণ এটির ব্যবস্থা ও পরিচালনা বজায় রাখতে সময় ব্যয় হয়।

আবর্জনা সংগ্রাহকের জন্য ব্যয় রয়েছে, ভাগ করা_পাত্রগুলি কম, অনন্য_পাত্র এমনকি কম এবং স্ট্যাক পরিচালিত বস্তুর খুব কম পরিমাণ রয়েছে।

কি shared_ptr"শেষ অবলম্বন" ?. না, এটি নয়: শেষ অবলম্বনটি আবর্জনা সংগ্রহকারী। shared_ptrআসলে std::প্রস্তাবিত শেষ অবলম্বন। তবে আপনি যদি পরিস্থিতিটি আমি বর্ণনা করে থাকেন তবে তা সমাধান হতে পারে।


9

পরবর্তী অধিবেশনে হার্ব সটার দ্বারা উল্লিখিত একটি জিনিস হ'ল প্রতিবার আপনি একটি অনুলিপি করার সময় shared_ptr<>একটি ইন্টারলকড ইনক্রিমেন্ট / হ্রাস আছে যা ঘটতে হবে। মাল্টি-কোর সিস্টেমের একাধিক-থ্রেড কোডে, মেমরি সিঙ্ক্রোনাইজেশন তুচ্ছ নয়। পছন্দটি দেওয়া হলে হয় স্ট্যাকের মানটি ব্যবহার করা ভাল, অথবা একটি unique_ptr<>এবং রেফারেন্সগুলি বা কাঁচা পয়েন্টারগুলির চারপাশে পাস করা ভাল।


1
বা shared_ptrলভ্যালু বা মূল্যের রেফারেন্স দিয়ে পাস করুন ...
রোন্যাগ

8
মুল বক্তব্যটি হ'ল, shared_ptrএটি কেবল রূপালী বুলেটের মতো ব্যবহার করবেন না যা এটি আপনার স্ট্যান্ডার্ডের কারণে সমস্ত স্মৃতি ফাঁসির সমস্যাগুলি সমাধান করবে। এটি একটি লোভনীয় ফাঁদ, তবে এটি এখনও সম্পদের মালিকানা সম্পর্কে সচেতন হওয়া গুরুত্বপূর্ণ এবং যদি সেই মালিকানা ভাগ shared_ptr<>না করা হয় তবে সেরা বিকল্প নয়।
অন্ধকার

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

1
@ জিবিজেবায়ানব: হ্যাঁ তারা সিপিইউ স্তরে রয়েছে, তবে একটি মাল্টি-কোর সিস্টেমে আপনি ক্যাশেগুলি অবৈধ করছেন এবং মেমরির প্রতিবন্ধকতাগুলি বাধ্য করছেন।
অন্ধকার

4
একটি গেম প্রোজেক্টে আমি কাজ করেছিলাম আমরা দেখতে পেলাম যে পারফরম্যান্সের পার্থক্যটি খুব তাত্পর্যপূর্ণ ছিল, যেখানে আমাদের দুটি বিভিন্ন ধরণের রেফ-কাউন্ট পয়েন্টার দরকার ছিল, একটি থ্রেডসেফ ছিল, যা ছিল না।
কাইলোটন

7

আমি মনে করি না যে শেষ "রিসর্ট" তিনি সঠিক শব্দটি ব্যবহার করেছিলেন কিনা তবে আমি বিশ্বাস করি যে তিনি যা বলেছিলেন তার আসল অর্থটি সর্বশেষ "পছন্দ" ছিল: পরিষ্কার মালিকানার শর্ত দেওয়া; অনন্য_পিটার, দুর্বল_পিটার, শেয়ার্ড_পিটার এমনকি নগ্ন পয়েন্টারগুলিরও তাদের জায়গা আছে।

তারা সকলেই যে বিষয়ে একমত হয়েছিলেন তা হ'ল আমরা (বিকাশকারী, বই লেখক ইত্যাদি) সি ++ 11 এর "শিক্ষণ পর্বে" এবং নিদর্শন এবং শৈলীর সংজ্ঞা দেওয়া হচ্ছে।

উদাহরণস্বরূপ, হার্ব ব্যাখ্যা করেছিলেন যে আমাদের কয়েকটি সিমনাল সি ++ বইয়ের নতুন সংস্করণগুলি আশা করা উচিত, যেমন কার্যকর সি ++ (মায়ার্স) এবং সি ++ কোডিং স্ট্যান্ডার্ডস (সুটার এবং আলেকজান্দ্রেস্কু), কয়েক বছর পরে শিল্পের অভিজ্ঞতা এবং সি নিয়ে সেরা অনুশীলনগুলি should ++ 11 টি প্যান আউট।


5

আমি মনে করি তিনি কী পাচ্ছেন তা হ'ল প্রত্যেকের কাছে শেয়ার_পিটার লেখার পক্ষে এটি সাধারণ হয়ে উঠেছে যখনই তারা একটি স্ট্যান্ডার্ড পয়েন্টার (এক ধরণের বিশ্বব্যাপী প্রতিস্থাপনের মতো) লিখে থাকতে পারে, এবং এটি আসলে ডিজাইনের পরিবর্তে বা কমপ্লেক্স হিসাবে ব্যবহৃত হচ্ছে অবজেক্ট তৈরি এবং মুছে ফেলার জন্য পরিকল্পনা।

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

অবজেক্ট এ, অন্য একটি অবজেক্ট বি-তে ভাগ করে নেওয়া পয়েন্টার যুক্ত করে একটি অবজেক্ট বি একটি এ 1 এবং এ এ 2 তৈরি করে এবং a1.otherA = a2 নির্ধারণ করে; এবং a2.otherA = a1; এখন বস্তু বি এর ভাগ করা পয়েন্টারগুলি এটি a1 তৈরি করতে ব্যবহৃত হয়েছিল, a2 সুযোগের বাইরে চলে যায় (কোনও ফাংশন শেষে বলে)) এখন আপনার ফুটো আছে- অন্য কেউ এ 1 এবং এ 2 কে বোঝায় না, তবে তারা একে অপরকে উল্লেখ করে যাতে তাদের রেফ গণনা সর্বদা 1 থাকে এবং আপনি ফাঁস করেন।

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

এটিকে মোড়ানোর জন্য: আমি মনে করি যে ওপি দ্বারা রেফারেন্স করা মন্তব্যগুলি এটিকে ফুটিয়ে তুলেছে:

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

সম্পাদনা: এমনকি যদি এর অর্থ "অজানা, আমার একটি শেয়ারড_পিটার ব্যবহার করা দরকার" আপনি এখনও এটিকে ভেবে দেখেছেন এবং ইচ্ছাকৃতভাবে এটি করছেন।


3

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

আমার বক্তব্যটি হ'ল শেয়ারড_পিটারটি শেষ রিসোর্টের পরিবর্তে আপনার প্রথম বিকল্প হওয়া উচিত। আপনি কী করছেন তা সম্পর্কে নিশ্চিত হন তবেই ডিফল্ট এবং অন্যান্য বিকল্প দ্বারা রেফারেন্স গণনা ব্যবহার করুন। আপনি আরও উত্পাদনশীল এবং আপনার কোড আরও শক্তিশালী হবে।


1

আমি প্রশ্নের উত্তর দেওয়ার চেষ্টা করব:

আমরা কীভাবে std :: শেয়ার_ptr ছাড়াই প্রোগ্রাম করতে পারি এবং এখনও নিরাপদে উপায়ে লাইফটাইম পরিচালনা করতে পারি?

সি ++ এর মেমোরি করার জন্য বিভিন্ন ধরণের বিভিন্ন পদ্ধতি রয়েছে, উদাহরণস্বরূপ:

  1. struct A { MyStruct s1,s2; };ক্লাস স্কোপে শেয়ারড_পিটারের পরিবর্তে ব্যবহার করুন । এটি কেবলমাত্র উন্নত প্রোগ্রামারদের জন্য কারণ এটির প্রয়োজন নির্ভরতাগুলি কীভাবে কাজ করে তা বোঝার জন্য এবং সেগুলি গাছের মধ্যে সীমাবদ্ধ করার জন্য নির্ভরতাগুলি নিয়ন্ত্রণ করার পর্যাপ্ত দক্ষতার প্রয়োজন। শিরোনাম ফাইলে শ্রেণীর ক্রম এর গুরুত্বপূর্ণ দিক aspect দেশীয় বিল্টিন সি ++ প্রকারের মধ্যে এই ব্যবহারটি ইতিমধ্যে সাধারণ বলে মনে হচ্ছে তবে প্রোগ্রামার-সংজ্ঞায়িত ক্লাসগুলির সাথে এটি ব্যবহার ক্লাসগুলির সমস্যার এই নির্ভরতা এবং ক্রমগুলির কারণে কম ব্যবহৃত হয়েছে বলে মনে হয়। এই সমাধানটিতে আকারের সমস্যাও রয়েছে। প্রোগ্রামাররা এতে সমস্যাগুলি ফরোয়ার্ড ঘোষণাপত্র বা অপ্রয়োজনীয় # অন্তর্ভুক্তি ব্যবহার করার প্রয়োজনীয়তা হিসাবে দেখায় এবং এইভাবে অনেক প্রোগ্রামার পয়েন্টারগুলির নিকৃষ্ট সমাধানে এবং পরে শেয়ারড_প্টারে ফিরে আসবে।
  2. এর MyClass &find_obj(int i);পরিবর্তে + ক্লোন () ব্যবহার করুন shared_ptr<MyClass> create_obj(int i);। অনেক প্রোগ্রামার নতুন বস্তু তৈরির জন্য কারখানা তৈরি করতে চান। শেয়ারড_পিটার এই ধরণের ব্যবহারের জন্য আদর্শভাবে উপযুক্ত। সমস্যাটি হ'ল এটি ইতিমধ্যে সহজ স্ট্যাক বা অবজেক্ট ভিত্তিক সমাধানের পরিবর্তে হিপ / ফ্রি স্টোর বরাদ্দ ব্যবহার করে জটিল মেমরি পরিচালন সমাধান গ্রহণ করে। ভাল সি ++ শ্রেণি শ্রেণিবিন্যাস কেবল তাদের মধ্যে একটি নয়, সমস্ত মেমরি পরিচালনা স্কিমকে সমর্থন করে। স্থানীয় ফাংশন স্কোপ ভেরিয়েবলের পরিবর্তে যদি প্রত্যাবর্তিত বস্তুটি ধারণকৃত বস্তুর ভিতরে সংরক্ষণ করা হয় তবে রেফারেন্স ভিত্তিক সমাধানটি কাজ করতে পারে। কারখানা থেকে ব্যবহারকারী কোডে মালিকানা পাস করা এড়ানো উচিত। Find_obj () ব্যবহার করার পরে অবজেক্টটি অনুলিপি করা এটি হ্যান্ডেল করার ভাল উপায় - পলিমর্ফিক অবজেক্টের জন্য রেফারেন্স প্যারামিটার বা ক্লোন () সহ সাধারণ কপি-কনস্ট্রাক্টর এবং সাধারণ কনস্ট্রাক্টর (বিভিন্ন শ্রেণীর) এটি পরিচালনা করতে পারে।
  3. পয়েন্টার বা শেয়ারড_প্টারের পরিবর্তে রেফারেন্সের ব্যবহার। প্রতিটি সি ++ শ্রেণিতে কনস্ট্রাক্টর থাকে এবং প্রতিটি রেফারেন্স ডেটা সদস্যকে আরম্ভ করা প্রয়োজন needs এই ব্যবহারটি পয়েন্টার এবং শেয়ার্ড_প্টারগুলির অনেকগুলি ব্যবহার এড়াতে পারে। আপনার মেমরিটি কোনও অবজেক্টের অভ্যন্তরে বা এর বাইরে রয়েছে কিনা তা আপনাকে বেছে নিতে হবে এবং সিদ্ধান্তের ভিত্তিতে স্ট্রাক্ট সমাধান বা রেফারেন্স সমাধান নির্বাচন করতে হবে। এই সমাধানের সমস্যাগুলি সাধারণত কন্সট্রাক্টর পরামিতিগুলি এড়ানো সম্পর্কিত যা সাধারণ তবে সমস্যাযুক্ত অনুশীলন এবং ক্লাসগুলির জন্য ইন্টারফেসগুলি কীভাবে ডিজাইন করা উচিত তা ভুল বোঝাবুঝি।

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

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

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

@নিকল বোলা: ওহ, এটি অন্যরকমভাবে পরিচালিত হয়; শ্রেণীর ইন্টারফেস একাধিক "সত্তা" সমর্থন করে। বস্তু এবং সত্তার মধ্যে 1: 1 ম্যাপিংয়ের পরিবর্তে আপনি ইন্টিটারে ব্যবহার করবেন। তারপরে সত্ত্বাগুলি কেবল অ্যারে থেকে সরিয়ে এটি খুব সহজেই মারা যায়। পুরো গেমটিতে কেবলমাত্র সংখ্যক সংস্থা রয়েছে এবং অ্যারেগুলির মধ্যে নির্ভরতা খুব বেশি সময় পরিবর্তন হয় না :)
tp1

2
না, unique_ptrকারখানার জন্য সবচেয়ে উপযুক্ত। আপনি একটি চালু করতে পারেন unique_ptrএকটি মধ্যে shared_ptrতবে এটি অন্যান্য দিক যেতে কথাটি অসম্ভব।
বেন ভয়েগ্ট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.