c++ উনল কেন সি++ একটি আবর্জনা সংগ্রাহক আছে না?




সি++ প্রোগ্রামিং বই ডাউনলোড (13)

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

যে বলেন, কেন এটা যোগ করা হয়েছে না? ইতিমধ্যে C ++ এর জন্য কিছু আবর্জনা সংগ্রাহক আছে। এই কি শুধু "কাজ সম্পন্ন চেয়ে সহজ বলেন" টাইপ জিনিস? অথবা এটি যুক্ত করা হয়নি এমন অন্য কোন কারণ আছে (এবং সি ++ 11 এ যোগ করা হবে না)?

ক্রস লিঙ্ক:

শুধু স্পষ্ট করার জন্য, আমি C ++ কে প্রথমবার তৈরি করার সময় একটি আবর্জনা সংগ্রাহক ছিল না কেন তা বুঝতে পেরেছি। আমি ভাবছি কেন সংগ্রাহক যোগ করা যাবে না।


কি ধরনের? এটা এমবেডেড ওয়াশিং মেশিন কন্ট্রোলার, সেল ফোন, ওয়ার্কস্টেশন বা সুপারকম্পিউটারের জন্য অপ্টিমাইজ করা উচিত?
এটা গাই প্রতিক্রিয়া বা সার্ভার লোডিং অগ্রাধিকার করা উচিত?
এটা অনেক মেমরি বা CPU এর প্রচুর ব্যবহার করা উচিত?

সি / সি ++ মাত্র অনেক ভিন্ন পরিস্থিতিতে ব্যবহার করা হয়। আমি স্মার্ট পয়েন্টার বুস্ট মত কিছু সন্দেহ অধিকাংশ ব্যবহারকারীদের জন্য যথেষ্ট হবে

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


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

বিজ্নে স্ট্র্রু স্ট্রাপ থেকে নিজেকে উদ্ধৃত করেছেন:

আমি আশা করি যে একটি আবর্জনা সংগ্রাহক যাকে বিকল্পভাবে সক্ষম করা যেতে পারে সেটি সি ++ 0x এর অংশ হতে পারে, তবে যথেষ্ট সংখ্যক প্রযুক্তিগত সমস্যা ছিল যা কেবলমাত্র একটি সংগ্রাহক বাকি ভাষার সাথে কিভাবে সংহত করে সে সম্পর্কে বিস্তারিত বিবরণের সাথে আমাকে করতে হবে , যদি প্রদান করা হয়। যেমনটি সমস্ত সি ++ 0x বৈশিষ্ট্যগুলির সাথে কেস হিসাবে, একটি পরীক্ষামূলক বাস্তবায়ন বিদ্যমান।

এখানে বিষয় ভাল আলোচনা here

সাধারণ ওভারভিউ:

সি ++ খুব শক্তিশালী এবং আপনি প্রায় কিছু করতে পারবেন। এই কারণে এটি স্বয়ংক্রিয়ভাবে আপনার কাছে অনেকগুলি জিনিস ধাক্কা দেয় না যা কর্মক্ষমতা প্রভাবিত করতে পারে। গার্বেজ সংগ্রহটি সহজেই স্মার্ট পয়েন্টারগুলির সাথে প্রয়োগ করা যেতে পারে (এমন বস্তু যা একটি রেফারেন্স গণনা সহ পয়েন্টারগুলি মোড়ানো করে, যা রেফারেন্স গণনা 0 পৌঁছলে স্বয়ংক্রিয়ভাবে নিজেকে মুছে দেয়)।

সি ++গুলি এমন প্রতিযোগীদের সাথে তৈরি হয়েছিল যেগুলি আবর্জনা সংগ্রহে ছিল না। দক্ষতা ছিল প্রধান উদ্বেগ যে সি ++ সি এবং অন্যান্যদের তুলনায় সমালোচনার মুখোমুখি হতে হয়েছিল।

২ ধরনের আবর্জনা সংগ্রহ আছে ...

পরিষ্কার আবর্জনা সংগ্রহ:

C ++ 0x ভাগ_পৃষ্ঠার সাথে তৈরি পয়েন্টারগুলির মাধ্যমে আবর্জনা সংগ্রহ করবে

যদি আপনি এটি চান তবে আপনি এটি ব্যবহার করতে পারবেন না, যদি আপনি এটি ব্যবহার করতে বাধ্য হন না।

আপনি বর্তমানে বুস্ট ব্যবহার করতে পারেন: shared_ptr পাশাপাশি যদি আপনি C ++ 0x এর জন্য অপেক্ষা করতে না চান।

আবদ্ধ আবর্জনা সংগ্রহ:

এটা স্বচ্ছ আবর্জনা সংগ্রহ যদিও না। যদিও ভবিষ্যতে সি ++ চশমা জন্য একটি ফোকাস পয়েন্ট হবে।

কেন Tr1 নিখরচায় আবর্জনা সংগ্রহ নেই?

অনেকগুলি জিনিস রয়েছে যা C ++ 0x এর ট্র1 হওয়া উচিত ছিল, পূর্ব সাক্ষাত্কারে বিজ্নে স্ট্রোস্ট্রুপ বলেছিল যে ট্র1টি তার পছন্দ অনুযায়ী যত বেশি ছিল না।


SHORT ANSWER: We don't know how to do garbage collection efficiently (with minor time and space overhead) and correctly all the time (in all possible cases).

LONG ANSWER: Just like C, C++ is a systems language; this means it is used when you are writing system code, eg, operating system. In other words, C++ is designed, just like C, with best possible performance as the main target. The language' standard will not add any feature that might hinder the performance objective.

This pauses the question: Why garbage collection hinders performance? The main reason is that, when it comes to implementation, we [computer scientists] do not know how to do garbage collection with minimal overhead, for all cases. Hence it's impossible to the C++ compiler and runtime system to perform garbage collection efficiently all the time. On the other hand, a C++ programmer, should know his design/implementation and he's the best person to decide how to best do the garbage collection.

Last, if control (hardware, details, etc.) and performance (time, space, power, etc.) are not the main constraints, then C++ is not the write tool. Other language might serve better and offer more [hidden] runtime management, with the necessary overhead.


আপনি যদি স্বয়ংক্রিয় আবর্জনা সংগ্রহ করতে চান তবে C ++ এর জন্য ভাল বাণিজ্যিক এবং সর্বজনীন ডোমেন আবর্জনা সংগ্রাহক রয়েছে। আবর্জনা সংগ্রহ উপযুক্ত যেখানে অ্যাপ্লিকেশনের জন্য, C ++ একটি চমৎকার আবর্জনা সংগৃহীত ভাষা যা এমন একটি কর্মক্ষমতা যা অন্যান্য আবর্জনা সংগৃহীত ভাষাগুলির সাথে সদৃশভাবে তুলনা করে। সি ++ এ স্বয়ংক্রিয় আবর্জনা সংগ্রহের আলোচনার জন্য সি ++ প্রোগ্রামিং ভাষা (4 য় সংস্করণ) দেখুন । দেখুন, হানস-জে। সি এবং সি ++ আবর্জনা সংগ্রহের জন্য বোহেমের সাইট ( archive )।

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

উৎস: http://www.stroustrup.com/bs_faq.html#garbage-collection

কেন এটিতে এটি তৈরি করা হয়নি, যদি আমি সঠিকভাবে মনে রাখি তবে এটি জি.সি. এর আগে উদ্ভাবিত হয়েছিল এবং আমি বিশ্বাস করি না যে ভাষাটি বেশ কয়েকটি কারণের জন্য জিসি থাকতে পারে (IE এর পিছনে IE এর সাথে সামঞ্জস্যপূর্ণ)

আশাকরি এটা সাহায্য করবে.


One of the fundamental principles behind the original C language is that memory is composed of a sequence of bytes, and code need only care about what those bytes mean at the exact moment that they are being used. Modern C allows compilers to impose additional restrictions, but C includes--and C++ retains--the ability to decompose a pointer into a sequence of bytes, assemble any sequence of bytes containing the same values into a pointer, and then use that pointer to access the earlier object.

While that ability can be useful--or even indispensable--in some kinds of applications, a language that includes that ability will be very limited in its ability to support any kind of useful and reliable garbage collection. If a compiler doesn't know everything that has been done with the bits that made up a pointer, it will have no way of knowing whether information sufficient to reconstruct the pointer might exist somewhere in the universe. Since it would be possible for that information to be stored in ways that the computer wouldn't be able to access even if it knew about them (eg the bytes making up the pointer might have been shown on the screen long enough for someone to write them down on a piece of paper), it may be literally impossible for a computer to know whether a pointer could possibly be used in the future.

An interesting quirk of many garbage-collected frameworks is that an object reference not defined by the bit patterns contained therein, but by the relationship between the bits held in the object reference and other information held elsewhere. In C and C++, if the bit pattern stored in a pointer identifies an object, that bit pattern will identify that object until the object is explicitly destroyed. In a typical GC system, an object may be represented by a bit pattern 0x1234ABCD at one moment in time, but the next GC cycle might replace all references to 0x1234ABCD with references to 0x4321BABE, whereupon the object would be represented by the latter pattern. Even if one were to display the bit pattern associated with an object reference and then later read it back from the keyboard, there would be no expectation that the same bit pattern would be usable to identify the same object (or any object).



Because modern C++ doesn't need garbage collection.

Bjarne Stroustrup's FAQ http://www.stroustrup.com/bs_faq.html#garbage-collection :

I don't like garbage. I don't like littering. My ideal is to eliminate the need for a garbage collector by not producing any garbage. That is now possible.

The situation, for code written these days (C++17 and following the official Core Guidelines ) is as follows:

  • Most memory ownership-related code is in libraries (especially those providing containers).
  • Most use of code involving memory ownership follows the RAII pattern , so allocation is made on construction and deallocation on destruction, which happens when exiting the scope in which something was allocated.
  • You do not explicitly allocate or deallocate memory directly .
  • Raw pointers do not own memory (if you've followed the guidelines), so you can't leak by passing them around.
  • If you're wondering how you're going to pass the starting addresses of sequences of values in memory - you'll be doing that with a span ; no raw pointer needed.
  • If you really need an owning "pointer", you use C++' standard-library smart pointers - they can't leak, and are quite efficient. Alternatively, you can pass ownership across scope boundaries with "owner pointers" . These are uncommon and must be used explicitly; and they allow for partial static checking against leaks.

"Oh yeah? But what about...

... if I just write code the way we used to write C++ in the old days?"

Indeed, you could just disregard all of the guidelines and write leaky application code - and it will compile and run (and leak), same as always.

But it's not a "just don't do that" situation, where the developer is expected to be virtuous and exercise a lot of self control; it's just not simpler to write non-conforming code, nor is it faster to write, nor is it better-performing. Gradually it will also become more difficult to write, as you would face an increasing "impedance mismatch" with what conforming code provides and expects.

... if I reintrepret_cast ? Or do pointer arithmetic? Or other such hacks?"

Indeed, if you put your mind to it, you can write code that messes things up despite playing nice with the guidelines. But:

  1. You would do this rarely (in terms of places in the code, not necessarily in terms of fraction of execution time)
  2. You would only do this intentionally, not accidentally.
  3. Doing so will stand out in a codebase conforming to the guidelines.
  4. It's the kind of code in which you would bypass the GC in another language anyway.

... library development?"

If you're a C++ library developer then you do write unsafe code involving raw pointers, and you are required to code carefully and responsibly - but these are self-contained pieces of code written by experts (and more importantly, reviewed by experts).


So, it's just like Bjarne said: There's really no motivation to collect garbage generally, as you all but make sure not to produce garbage. GC is becoming a non-problem with C++.

That is not to say GC isn't an interesting problem for certain specific applications, when you want to employ custom allocation and de-allocations strategies. For those you would want custom allocation and de-allocation, not a language-level GC.


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

কিছু তৃতীয় পক্ষের আবর্জনা সংগ্রহ পদ্ধতিতে আবদ্ধ স্মার্ট পয়েন্টারগুলির কিছু ফর্ম ব্যবহার করা থেকে আপনাকে বাধা দেয় না। মনে হচ্ছে মাইক্রোসফট COM এর সাথে এমন কিছু করছে এবং এটি ভালভাবে চলেনি।


যদিও এটি একটি পুরনো প্রশ্ন, এখনও এমন একটি সমস্যা রয়েছে যেটি আমি কাউকেই ঠিকঠাক করে দেখছি না: আবর্জনা সংগ্রহ উল্লেখ করা প্রায় অসম্ভব।

বিশেষ করে, সি ++ মানটি সেই আচরণকে কিভাবে বাস্তবায়ন করে তার পরিবর্তে বাহ্যিকভাবে পর্যবেক্ষণযোগ্য আচরণের পরিপ্রেক্ষিতে ভাষাটি নির্দিষ্ট করার জন্য বেশ সতর্ক। আবর্জনা সংগ্রহের ক্ষেত্রে, কার্যত কোন বাহ্যিকভাবে পর্যবেক্ষণযোগ্য আচরণ নেই।

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

যদি আপনি বস্তুগুলি সরাতে না পারেন, তবে আপনি আপনার একক, সামঞ্জস্যপূর্ণ মেমরি স্থান তৈরি করতে পারবেন না যা থেকে আপনার বরাদ্দ করা হয় - এবং এর অর্থ হল আপনার হিপ (অথবা বিনামূল্যের দোকান, অথবা আপনি যেটিকে কল করতে চান) পারেন, এবং সম্ভবত , সময়ের সাথে বিভক্ত হয়ে। এটি, পরিবর্তে, অনুরোধের পরিমাণ থেকে বেশি মেমরি মুক্ত থাকলেও, সফল থেকে বরাদ্দ প্রতিরোধ করতে পারে।

যদিও এটি কিছু গ্যারান্টি নিয়ে আসতে পারে যা বলতে পারে (মূলত) যে আপনি যদি বার বার বরাদ্দকরণের একই প্যাটার্ন পুনরাবৃত্তি করেন এবং এটি প্রথমবার সফল হয় তবে পরবর্তী পুনরাবৃত্তি সফল হবে, তবে বরাদ্দকৃত স্মৃতি পুনরাবৃত্তি মধ্যে প্রবেশযোগ্য হয়ে ওঠে। এটি একটি দুর্বল গ্যারান্টি এটি মূলত নিরর্থক, কিন্তু আমি এটি শক্তিশালী করার কোন যুক্তিসঙ্গত আশা দেখতে পাচ্ছি না।

এমনকি তাই, এটি C ++ এর জন্য প্রস্তাবিত তুলনায় শক্তিশালী। পূর্ববর্তী প্রস্তাব [সতর্কতা: পিডিএফ] (যে বাদ পড়ে) সব কিছু গ্যারান্টি দেয় না। প্রস্তাবের ২8 টি পৃষ্ঠায়, আপনি বহিরাগতভাবে পর্যবেক্ষণযোগ্য আচরণের পথে যা পেয়েছিলেন তা একক (নন-আদর্শিক) নোট বলেছিল:

[দ্রষ্টব্য: আবর্জনা সংগৃহীত প্রোগ্রামগুলির জন্য, উচ্চমানের হোস্ট করা বাস্তবায়নটি পুনরুদ্ধারযোগ্য অ্যাক্সেসযোগ্য মেমরির পরিমাণ সর্বাধিক করার চেষ্টা করা উচিত। নোট লিখুন]

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

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

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


Stroustrup 2013 এ যাচ্ছে কিছু ভাল মন্তব্য করেছেন গোটা সম্মেলন।

এই ভিডিওতে প্রায় 25m50s এ যান। (আমি প্রকৃতপক্ষে পুরো ভিডিওটি দেখানোর সুপারিশ করব, কিন্তু এটি আবর্জনা সংগ্রহ সম্পর্কে স্টাফগুলিতে চলে যাবে।)

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

আধুনিক সি ++ সহ, এবং C ++ 11 এ আমাদের থাকা উপাদানগুলি, সীমিত পরিস্থিতিতে ব্যতীত আবর্জনা সংগ্রহ আর পছন্দসই নয়। প্রকৃতপক্ষে, এমনকি যদি একটি ভাল আবর্জনা সংগ্রাহক প্রধান সি ++ কম্পাইলারগুলির মধ্যে একটিতেও নির্মিত হয় তবে আমি মনে করি এটি প্রায়শই ব্যবহৃত হবে না। জিসি এড়াতে কঠিন, কঠিন হবে না।

তিনি এই উদাহরণ দেখায়:

void f(int n, int x) {
    Gadget *p = new Gadget{n};
    if(x<100) throw SomeException{};
    if(x<200) return;
    delete p;
}

এই সি ++ মধ্যে অনিরাপদ। কিন্তু জাভাতে এটি অনিরাপদ! সি ++ এ, যদি ফাংশনটি প্রথম দিকে ফিরে আসে তবে delete হবে না। কিন্তু যদি আপনার জাভা জুড়ে সম্পূর্ণ আবর্জনা সংগ্রহ থাকে তবে আপনি কেবল একটি পরামর্শ পাবেন যে "ভবিষ্যতে কোনও সময়ে" বস্তুটি ধ্বংস হয়ে যাবে ( আপডেট: এটি আরও খারাপ। জাভা কখনও ফিনিলারকে কল করার প্রতিশ্রুতি দেয় না - এটা হয়তো কখনও বলা হবে না)। গ্যাজেটটি খোলা ফাইল হ্যান্ডেল, বা ডাটাবেসের সাথে সংযোগ, বা পরবর্তী সময়ে কোনও ডাটাবেসে লেখার জন্য আপনি buffered ডেটা থাকলে এটি যথেষ্ট ভাল নয়। যত তাড়াতাড়ি সম্ভব এই সংস্থানগুলি মুক্ত করার জন্য গ্যাজেটটি শেষ হওয়ার সাথে সাথেই আমরা তা ধ্বংস করতে চাই। আপনি আপনার ডেটাবেস সার্ভারের হাজার হাজার ডেটাবেস সংযোগগুলির সাথে সংগ্রাম করতে চান না যা আর প্রয়োজন হয় না - এটি আপনার প্রোগ্রামটি কাজ শেষ করার বিষয়ে জানে না।

তাই সমাধান কি? কয়েকটি পন্থা আছে। সুস্পষ্ট পদ্ধতি, যা আপনি আপনার বস্তুর বেশিরভাগ ক্ষেত্রে ব্যবহার করতে পারবেন:

void f(int n, int x) {
    Gadget p = {n};  // Just leave it on the stack (where it belongs!)
    if(x<100) throw SomeException{};
    if(x<200) return;
}

এই টাইপ কম অক্ষর লাগে। এটা পথে পেয়ে new নেই। এটা আপনি Gadget দুইবার টাইপ করার প্রয়োজন হয় না। বস্তুর ফাংশন শেষে ধ্বংস করা হয়। যদি আপনি চান এই, এটা খুব স্বজ্ঞাত। Gadget গুলি int বা double হিসাবে আচরণ। পূর্বাভাসযোগ্য, সহজে পড়া, সহজ শেখান। সবকিছু একটি 'মান'। কখনও কখনও একটি বড় মান, কিন্তু মান শেখান সহজ হয় কারণ আপনি পয়েন্টার (অথবা রেফারেন্স) সঙ্গে আপনি এই 'কর্ম একটি দূরত্ব' জিনিস আছে না।

আপনি যে বস্তুগুলি তৈরি করেছেন সেগুলি শুধুমাত্র তাদের তৈরি ফাংশনে ব্যবহার করা হয় এবং সম্ভবত শিশু ক্রিয়াকলাপগুলিতে ইনপুট হিসাবে পাস করা হয়। বস্তুগুলি ফেরত দেওয়ার সময় প্রোগ্রামারকে 'মেমরি পরিচালনার' কথা ভাবতে হবে না বা সফ্টওয়্যারের ব্যাপকভাবে পৃথক অংশগুলিতে বস্তুগুলি ভাগ করা উচিত নয়।

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

এটি একটি দক্ষতা সমস্যা মত মনে হতে পারে। আমি যদি foo() থেকে একটি গ্যাজেট ফেরত দিতে চান কি? C ++ 11 এর সরানো স্যাম্যান্টিকগুলি বড় বস্তু ফেরত আরো সহজ করে তোলে। শুধু Gadget foo() { ... } লিখুন Gadget foo() { ... } এবং এটি কেবল কাজ করবে এবং দ্রুত কাজ করবে। আপনি && নিজেকে সঙ্গে জগাখিচুড়ি করতে হবে না, শুধু মান দ্বারা জিনিস ফেরত এবং ভাষা প্রায়ই প্রয়োজনীয় অপ্টিমাইজেশান করতে সক্ষম হবে। (এমনকি C ++ 03 আগেও, কম্পাইলারগুলি অপ্রয়োজনীয় অনুলিপি এড়াতে একটি অসাধারণ ভাল কাজ করেছিল।)

স্ট্রাউস্ট্রপপ ভিডিওটিতে অন্য কোথাও বলেছিলেন (উদাহরণস্বরূপ): "কেবলমাত্র একজন কম্পিউটার বিজ্ঞানী কেবল একটি বস্তুর অনুলিপি করার এবং তারপরে মূলটিকে ধ্বংস করার জন্য জোরালো পরামর্শ দেবেন। (দর্শকদের হাসি)। কেন বস্তুকে সরাসরি নতুন অবস্থানে স্থানান্তর করবেন না? (কম্পিউটার বিজ্ঞানী না) আশা করি। "

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

যদি এটি আপনার জন্য কাজ না করে তবে আপনি unique_ptr ব্যবহার করতে পারেন, অথবা এটি ব্যর্থ করতে পারেন, shared_ptr । ভাল লেখা C ++ 11 মেমরি পরিচালনার ক্ষেত্রে যখন এটি অন্যান্য ভাষার চেয়ে ছোট, সহজে পড়া এবং সহজে শেখানো হয়।


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

  • বস্তুর নির্ধারক জীবনকাল (রেফারেন্স কাউন্টিং আপনাকে এটি দেয়, তবে জিসি নেই। যদিও এটি একটি বড় চুক্তি নয়)।
  • বস্তু আবর্জনা সংগ্রহ করা হয় যখন একটি ধ্বংসকারী ছুড়ে যদি কি হবে? বেশিরভাগ ভাষা এই ব্যতিক্রমটি উপেক্ষা করে, কারণ এটিগুলি কোনও ট্র্যাজেড ট্র্যাক করতে সক্ষম হয় না তবে এটি সম্ভবত C ++ এর জন্য গ্রহণযোগ্য সমাধান নয়।
  • কিভাবে এটি সক্রিয় / নিষ্ক্রিয়? স্বাভাবিকভাবেই এটি একটি কম্পাইলের সময় সিদ্ধান্ত হতে পারে তবে GC বনাম কোডের জন্য লেখা কোডটি যা GC- এর জন্য লেখা হয় তা খুব ভিন্ন এবং সম্ভবত অসঙ্গত হতে যাচ্ছে। কিভাবে আপনি এই reconcile?

এই সম্মুখীন সমস্যা মাত্র কয়েক।


All the technical talking is overcomplicating the concept.

If you put GC into C++ for all the memory automatically then consider something like a web browser. The web browser must load a full web document AND run web scripts. You can store web script variables in the document tree. In a BIG document in a browser with lots of tabs open, it means that every time the GC must do a full collection it must also scan all the document elements.

On most computers this means that PAGE FAULTS will occur. So the main reason, to answer the question is that PAGE FAULTS will occur. You will know this as when your PC starts making lots of disk access. This is because the GC must touch lots of memory in order to prove invalid pointers. When you have a bona fide application using lots of memory, having to scan all objects every collection is havoc because of the PAGE FAULTS. A page fault is when virtual memory needs to get read back into RAM from disk.

So the correct solution is to divide an application into the parts that need GC and the parts that do not. In the case of the web browser example above, if the document tree was allocated with malloc, but the javascript ran with GC, then every time the GC kicks in it only scans a small portion of memory and all PAGED OUT elements of the memory for the document tree does not need to get paged back in.

To further understand this problem, look up on virtual memory and how it is implemented in computers. It is all about the fact that 2GB is available to the program when there is not really that much RAM. On modern computers with 2GB RAM for a 32BIt system it is not such a problem provided only one program is running.

As an additional example, consider a full collection that must trace all objects. First you must scan all objects reachable via roots. Second scan all the objects visible in step 1. Then scan waiting destructors. Then go to all the pages again and switch off all invisible objects. This means that many pages might get swapped out and back in multiple times.

So my answer to bring it short is that the number of PAGE FAULTS which occur as a result of touching all the memory causes full GC for all objects in a program to be unfeasible and so the programmer must view GC as an aid for things like scripts and database work, but do normal things with manual memory management.

And the other very important reason of course is global variables. In order for the collector to know that a global variable pointer is in the GC it would require specific keywords, and thus existing C++ code would not work.


এখানে বিতর্ক যোগ করুন।

আবর্জনা সংগ্রহের সাথে পরিচিত সমস্যা রয়েছে এবং তাদের বোঝার জন্য C ++ এ কোনও নেই কেন তা বুঝতে সহায়তা করে।

1. পারফরম্যান্স?

প্রথম অভিযোগ প্রায়ই কর্মক্ষমতা সম্পর্কে, কিন্তু অধিকাংশ মানুষ সত্যিই তারা কি বিষয়ে কথা বলা হয় না। Martin Beckett দ্বারা চিত্রিত হিসাবে সমস্যাটি প্রতি পারফরম্যান্স নাও হতে পারে, তবে কর্মক্ষমতা পূর্বাভাস।

বর্তমানে জিসি এর 2 টি পরিবার রয়েছে যা ব্যাপকভাবে নিযুক্ত করা হয়:

  • মার্ক-এবং-সুইপ ধরনের
  • রেফারেন্স-কাউন্টিং ধরনের

Mark And Sweep দ্রুত (সামগ্রিক কর্মক্ষমতাতে কম প্রভাব) কিন্তু এটি "বিশ্বকে নিশ্চিহ্ন করা" সিন্ড্রোম থেকে ভুগছে: অর্থাত্ জিসি কক্সবাজারে গেলে, অন্য সব কিছুই জি সি পরিষ্কারের না হওয়া পর্যন্ত থামানো হয়। আপনি যদি কয়েক মিলিসেকেন্ডে উত্তরের একটি সার্ভার তৈরি করতে চান তবে কিছু লেনদেন আপনার প্রত্যাশাগুলিতে বাস করবে না :)

Reference Counting সমস্যাটি আলাদা: রেফারেন্স-কাউন্টিং ওভারহেড যোগ করে, বিশেষ করে মাল্টি-থ্রেডিং পরিবেশগুলিতে, কারণ আপনাকে একটি পারমাণবিক গণনা করতে হবে। উপরন্তু রেফারেন্স চক্রগুলির সমস্যা আছে যাতে আপনাকে চক্রগুলি সনাক্ত করতে এবং তাদের নির্মূল করার জন্য একটি চতুর এলগরিদম প্রয়োজন (সাধারণত "বিশ্বকে নিশ্চিহ্ন করা" খুব কমই কার্যকর হলেও)। সাধারণভাবে, আজকের মতো, এই ধরনের (যদিও সাধারণত বেশি প্রতিক্রিয়াশীল বা বরং কম হ্রাস করা হয়) Mark And Sweep চেয়ে ধীর।

আইফেল বাস্তবায়নকারীরা একটি Reference Counting গার্বেজ কালেক্টর বাস্তবায়ন করার চেষ্টা করছে যা "ফ্রিজ দ্য ওয়ার্ল্ড" দৃষ্টিভঙ্গি ব্যতীত Mark And Sweep অনুরূপ বিশ্বব্যাপী কর্মক্ষমতা থাকবে। এটি জিসি (সাধারণত) জন্য একটি পৃথক থ্রেড প্রয়োজন। অ্যালগরিদমটি একটু ভীতিকর (শেষ পর্যন্ত) ছিল তবে কাগজটি একবারে ধারণাগুলি একত্রিত করার এবং "সহজ" সংস্করণ থেকে পূর্ণাঙ্গ সংস্করণে অ্যালগরিদমের বিবর্তন দেখানোর একটি ভাল কাজ করে। প্রস্তাবিত পাঠ্য যদি কেবল আমি পিডিএফ ফাইলে আমার হাত রাখি ...

2. সম্পদ অধিগ্রহণ শুরু হয়

এটি C++ এ একটি সাধারণ বিদারণ যা আপনি কোনও বস্তুর মধ্যে সংস্থানের মালিকানা মোড়ানো হবে যাতে তারা সঠিকভাবে মুক্তি পেতে পারে। আমাদের বেশিরভাগ মেমরির জন্য ব্যবহৃত হয় কারণ আমাদের বর্জ্য সংগ্রহ নেই, তবে এটি অন্যান্য উপায়েও উপকারী হয়:

  • লক (মাল্টি থ্রেড, ফাইল হ্যান্ডেল, ...)
  • সংযোগ (একটি ডাটাবেস, অন্য সার্ভার, ...)

ধারণা বস্তুর জীবনকাল সঠিকভাবে নিয়ন্ত্রণ করা হয়:

  • যতক্ষণ আপনি এটি প্রয়োজন জীবিত হওয়া উচিত
  • আপনি এটি সম্পন্ন করা হয় যখন এটি হত্যা করা উচিত

জিসি এর সমস্যা হল যে যদি এটি পূর্বের এবং শেষ পর্যন্ত গ্যারান্টিকে সাহায্য করে তবে ... এই "চূড়ান্ত" যথেষ্ট নাও হতে পারে। যদি আপনি একটি লক প্রকাশ করেন, আপনি সত্যিই এটি মুক্তি পেতে চান, যাতে এটি কোনও কল ব্লক না করে!

জিসি সঙ্গে ভাষা দুটি কাজ আশপাশ আছে:

  • স্ট্যাক বরাদ্দ করার সময় জিসি ব্যবহার করবেন না: এটি সাধারণত কার্য সম্পাদনের সমস্যাগুলির জন্য, কিন্তু আমাদের ক্ষেত্রে এটি সত্যিই সহায়তা করে, কারণ সুযোগটি সারাজীবনকে সংজ্ঞায়িত করে
  • কনস্ট্রাক্ট using ... কিন্তু এটি স্পষ্ট (দুর্বল) RAII যখন C ++ RAII তে অন্তর্নিহিত হয় যাতে ব্যবহারকারী অজানাভাবে ত্রুটি তৈরি করতে পারে ( using শব্দ বাদ দিয়ে)

3. স্মার্ট পয়েন্টার

স্মার্ট পয়েন্টারগুলি প্রায়ই C++ মেমরি হ্যান্ডেল করার জন্য রূপালী বুলেট হিসাবে উপস্থিত হয়। প্রায়শই আমি শুনেছি: আমরা সব পরে জিসি প্রয়োজন নেই, আমরা স্মার্ট পয়েন্টার আছে।

এক ভুল হতে পারে না।

স্মার্ট পয়েন্টার সাহায্য করে: auto_ptr এবং unique_ptr RAII ধারণাগুলি ব্যবহার করে, এটি অত্যন্ত উপকারী। তারা খুব সহজ যে আপনি তাদের দ্বারা বেশ সহজেই লিখতে পারেন।

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

এটা দুর্দান্ত, সব পরে জন্য বুস্ট কি, কিন্তু এটি একটি রূপালী বুলেট না। প্রকৃতপক্ষে, shared_ptr এর মূল সমস্যা shared_ptr এটি Reference Counting দ্বারা বাস্তবায়িত একটি জিসি অনুকরণ করে কিন্তু আপনাকে নিজের দ্বারা চক্র সনাক্তকরণ বাস্তবায়ন করতে হবে ... Urg

অবশ্যই এই weak_ptr জিনিসটি আছে, তবে দুর্ভাগ্যবশত আমি ইতিমধ্যেই shared_ptr কারণে shared_ptr ব্যবহার করার পরেও মেমরি shared_ptr দেখেছি ... এবং যখন আপনি মাল্টি থ্রেডেড পরিবেশে থাকেন, তখন এটি সনাক্ত করা খুব কঠিন!

4. সমাধান কি?

কোন রূপালী বুলেট নেই, কিন্তু সবসময় হিসাবে, এটা স্পষ্টভাবে সম্ভব। জিসি অনুপস্থিতিতে মালিকানার বিষয়টি পরিষ্কার হতে হবে:

  • যদি সম্ভব হয়, একটি প্রদত্ত সময় একক মালিক থাকার পছন্দ
  • যদি না হয়, নিশ্চিত করুন যে আপনার ক্লাসের চিত্রটিতে মালিকানা সম্পর্কিত কোনও চক্র নেই এবং weak_ptr অ্যাপ্লিকেশনের সাথে তাদের বিরতি weak_ptr

তাই প্রকৃতপক্ষে, একটি GC আছে দুর্দান্ত হবে ... তবে এটি কোন তুচ্ছ বিষয় নয়। এবং গড় সময়, আমরা শুধু আমাদের ভেতরে পাকানো প্রয়োজন।





c++11