سؤال

أنا لا أسأل هذا السؤال لأن من مزايا جمع القمامة أولا وقبل كل شيء.السبب الرئيسي في بلدي على هذا السؤال هو أن أعرف أن Bjarne Stroustrup وقال C++ سوف يكون جامع البيانات المهملة في بعض نقطة في الوقت المناسب.

وقال مع ذلك, لماذا لم يكن المضافة ؟ هناك بالفعل بعض جامعي القمامة C++.هذا هو مجرد واحدة من تلك "وقال أسهل من القيام به" نوع الأشياء ؟ أم أن هناك أسباب أخرى لم يتم إضافة (و لن تضاف في C++11)?

عبر الروابط:

فقط لتوضيح أنا أفهم الأسباب C++ لم يكن أحد هواة جمع القمامة عندما أنشئت لأول مرة.أنا أتساءل لماذا جامع لا يمكن إضافة في.

هل كانت مفيدة؟

المحلول

ضمني جمع القمامة يمكن إضافتها في, لكنه لم يجعل قطع.وربما يرجع ذلك إلى ليس فقط تنفيذ مضاعفات ، ولكن أيضا بسبب أن الناس لا يجري قادرة على التوصل إلى توافق عام في الآراء سريع بما فيه الكفاية.

اقتباس من Bjarne Stroustrup نفسه:

تمنيت أن جامع القمامة والتي يمكن أن يكون اختياريا تمكين سيكون جزءا من C++0x ، ولكن كانت هناك ما يكفي من المشاكل التقنية التي لدي فقط مفصل مواصفات من جامع يتكامل مع بقية اللغة, إذا قدمت.كما هو الحال أساسا كل من C++0x الميزات ، تجريبي تنفيذ موجود.

هناك مناقشة الموضوع هنا.

لمحة عامة:

C++ هي قوية جدا و يسمح لك أن تفعل أي شيء تقريبا.ولهذا السبب فإنه لا تلقائيا دفع العديد من الأشياء وراءك التي قد تؤثر على الأداء.جمع القمامة يمكن تنفيذها بسهولة مع المؤشرات الذكية (الكائنات التي التفاف المؤشرات مع مرجع ، والتي السيارات حذف أنفسهم عندما مرجع تصل إلى 0).

C++ بنيت مع المنافسين في اعتبارنا أن لم يكن لديك جمع القمامة.الكفاءة كان مصدر القلق الرئيسي الذي C++ لدرء انتقادات من مقارنة C وغيرها.

هناك 2 أنواع من جمع القمامة...

صريح جمع القمامة:

C++0x سوف يكون جمع القمامة من خلال المؤشرات التي تم إنشاؤها مع shared_ptr

إذا كنت تريد ذلك يمكنك استخدامه إذا كنت لا تريد ذلك لا تضطر إلى استخدامه.

يمكنك حاليا استخدام دفعة:shared_ptr وكذلك إذا كنت لا تريد الانتظار C++0x.

ضمني جمع القمامة:

فإنه لا يكون شفاف جمع القمامة على الرغم من.وسوف تكون نقطة التركيز في المستقبل C++ المواصفات على الرغم من.

لماذا Tr1 لا يكون ضمنيا جمع القمامة ؟

هناك الكثير من الأشياء التي tr1 C++0x ينبغي ان يكون ، Bjarne Stroustrup في المقابلات السابقة ذكرت أن tr1 لم يكن بقدر ما نود.

نصائح أخرى

إضافة إلى النقاش هنا.

هناك قضايا معروفة مع جمع القمامة ، فهم لهم يساعد على فهم لماذا لا يوجد في C++.

1.الأداء ؟

الشكوى الأولى هي في كثير من الأحيان عن أداء, ولكن معظم الناس لا يدركون حقا ما الذي يتحدثون عنه.كما يتضح من Martin Beckett المشكلة قد لا تكون أداء في حد ذاتها ، ولكن التنبؤ الأداء.

يوجد حاليا 2 أسر GC التي يتم نشرها على نطاق واسع:

  • مارك-و-اكتساح نوع
  • عد المرجع نوع

على Mark And Sweep أسرع (أقل تأثير على الأداء العام) ولكنه يعاني من "تجميد العالم" المتلازمة:أي عندما GC ركلات في كل شيء آخر هو توقف حتى GC جعلت تنظيف.إذا كنت ترغب في بناء الخادم التي الإجابات في أجزاء قليلة من الثانية...بعض الصفقات التي لا ترقى إلى مستوى التوقعات الخاصة بك :)

مشكلة Reference Counting مختلفة:عد المرجع يضيف النفقات العامة ، وخاصة في خيوط متعددة البيئات لأنك تحتاج إلى أن يكون ذرية العد.وعلاوة على ذلك هناك مشكلة المرجعية دورات لذلك تحتاج خوارزمية ذكية للكشف عن تلك الدورات والقضاء عليها (عموما تنفذ من قبل "تجميد العالم" أيضا ، على الرغم من أقل تواترا).في العامة ، وذلك اعتبارا من اليوم, هذا النوع (على الرغم من عادة أكثر استجابة أو بالأحرى تجميد أقل في كثير من الأحيان) هو أبطأ من Mark And Sweep.

لدي رأيت ورقة إيفل منفذي التي كانت تحاول تنفيذ Reference Counting جامع القمامة سيكون لها مماثلة العالمية الأداء Mark And Sweep دون "تجميد العالم" الجانب.المطلوب موضوع مستقل عن GC (نموذجي).الخوارزمية كانت مخيفة بعض الشيء (في النهاية) ولكن قدمت ورقة عمل جيد من إدخال مفاهيم في وقت واحد و تبين تطور خوارزمية من "بسيطة" النسخة كاملة واحدة.القراءة الموصى بها إلا إذا كنت قد وضعت يدي على ملف PDF...

2.الموارد الاستحواذ هو التهيئة

انها لغة مشتركة في C++ التي سوف التفاف ملكية الموارد داخل كائن لضمان أن يتم الافراج عنهم.انها تستخدم في الغالب الذاكرة بما أننا لا نملك جمع القمامة ، ولكن من المفيد أيضا مع ذلك العديد من الحالات الأخرى:

  • أقفال (موضوع متعدد الصفحات ، ملف التعامل معها،...)
  • اتصالات (إلى قاعدة بيانات ملقم آخر،...)

الفكرة هي أن التحكم بشكل صحيح عن عمر من وجوه:

  • ينبغي أن يكون على قيد الحياة طالما كنت في حاجة إليها
  • ينبغي أن يكون قتل عندما كنت فعلت مع ذلك

مشكلة GC هو أنه إذا كان ذلك يساعد في السابق وفي نهاية المطاف ضمانات في وقت لاحق...هذا "في نهاية المطاف" قد لا تكون كافية.إذا كنت الافراج عن قفل, كنت أود حقا أن يكون صدر الآن, حيث أن ذلك لا يمنع أي مزيد من المكالمات!

اللغات مع GC يكون اثنين احترف العمل:

  • لا تستخدم GC عندما تخصيص مكدس كافية:انها عادة مشكلات في الأداء, ولكن في حالتنا أنه يساعد حقا منذ نطاق يحدد مدى الحياة
  • using بناء...لكنه صريح (ضعيف) RAII بينما في C++ RAII ضمنا بحيث لا يمكن للمستخدم دون قصد جعل خطأ (قبل حذف using الكلمات الرئيسية)

3.المؤشرات الذكية

المؤشرات الذكية في كثير من الأحيان تظهر رصاصة فضية للتعامل مع الذاكرة في C++.في كثير من الأحيان سمعت:نحن لا نحتاج GC بعد كل شيء, لأن لدينا مؤشرات الذكية.

واحد لا يمكن أن يكون أكثر خطأ.

المؤشرات الذكية تساعد: auto_ptr و unique_ptr استخدام RAII مفاهيم مفيدة للغاية في الواقع.فهي بسيطة جدا التي يمكنك كتابتها بنفسك بسهولة تامة.

عندما تحتاج إلى حصة ملكية ومع ذلك فإنه يحصل على أكثر صعوبة:قد يمكنك مشاركة من بين مواضيع متعددة و هناك عدد قليل من دقيق المسائل مع التعامل مع العد.ولذلك ، فمن الطبيعي أن يذهب نحو shared_ptr.

انه لشيء رائع, هذا ما دفعة بعد كل شيء, ولكن هذا ليس حلا سحريا.في الواقع ، فإن القضية الرئيسية مع shared_ptr هو أنه يحاكي GC تنفذها Reference Counting ولكن تحتاج إلى تنفيذ دورة الكشف عن كل شيء بنفسك...Urg

بالطبع هناك هذا weak_ptr الشيئ, لكن للأسف رأينا بالفعل تسرب الذاكرة على الرغم من استخدام shared_ptr لأن هذه الدورات...و عندما كنت في متعدد الخيوط البيئة ، من الصعب جدا الكشف عن!

4.ما هو الحل ؟

لا يوجد حل سحري ، ولكن كما هو الحال دائما, إنه بالتأكيد ممكن.في غياب GC واحد بحاجة إلى أن تكون واضحة على الملكية:

  • تفضل وجود مالك واحد في وقت معين ، إذا كان ذلك ممكنا
  • إذا لم يكن كذلك ، تأكد من أن فئة الرسم ليس لديها أي دورة المتعلقة بالملكية وكسر لهم خفية تطبيق weak_ptr

حتى في الواقع, سيكون أمرا رائعا أن يكون GC...ومع ذلك فإنه لا تافهة المسألة.و في الوقت نفسه ، علينا فقط أن نشمر عن سواعدنا.

ماذا اكتب ؟ يجب أن يكون الأمثل جزءا لا يتجزأ من غسالة وحدات التحكم, الهواتف المحمولة, محطات العمل أو أجهزة الكمبيوتر العملاقة?
يجب أن أولويات الاستجابة واجهة المستخدم الرسومية أو ملقم التحميل ؟
ينبغي أن تستخدم الكثير من الذاكرة أو الكثير من المعالجة المركزية ؟

C/c++ يستخدم في الكثير من الظروف المختلفة.وأظن أن شيئا مثل زيادة المؤشرات الذكية سوف تكون كافية بالنسبة لمعظم المستخدمين

تحرير - التلقائي جامعي القمامة ليست مشكلة الكثير من الأداء (يمكنك دائما شراء المزيد من خادم) انها مسألة predicatable الأداء.
لا نعلم متى GC هو الذهاب إلى ركلة في مثل توظيف خدار طيار ، أكثر من مرة فهي كبيرة - ولكن عندما كنت حقا بحاجة إلى الاستجابة!

واحد من أكبر الأسباب التي C++ لا يكون بنيت في جمع القمامة هو أن الحصول على جمع القمامة للعب لطيفة مع destructors هو حقا من الصعب حقا.بقدر ما أعرف ، لا أحد يعرف حقا كيف تحل تماما حتى الآن.هناك الكثير من القضايا للتعامل مع:

  • القطعية أعمار الكائنات (إشارة العد يعطيك هذا ، ولكن GC لا.على الرغم من أنه قد لا يكون كبيرا).
  • ماذا يحدث إذا المدمر يلقي عند الكائن القمامة التي يتم جمعها ؟ معظم اللغات تجاهل هذا الاستثناء لأن هناك حقا أي كتلة catch أن تكون قادرة على نقل ذلك ، ولكن قد لا يكون هذا هو حل مقبول C++.
  • كيفية تمكين/تعطيل ذلك ؟ وبطبيعة الحال فإنه من المحتمل أن يكون وقت الترجمة القرار ولكن الكود الذي يكتب GC مقابل البرمجية التي يتم كتابتها لا GC ستكون مختلفة جدا وربما غير متوافق.كيف يمكن التوفيق بين ذلك ؟

هذه هي مجرد عدد قليل من المشاكل التي تواجهها.

على الرغم من أن هذا هو القديمة السؤال لا يزال هناك مشكلة واحدة أن أنا لا أرى أي شخص وقد تناول في كل شيء:جمع القمامة من المستحيل تقريبا تحديد.

ولا سيما C++ القياسية جدا دقيق لتحديد اللغة من حيث خارجيا يمكن ملاحظتها في السلوك بدلا من كيفية تنفيذ يحقق هذا السلوك.في حالة جمع القمامة ، ومع ذلك ، هناك هو تقريبا لا خارجيا يمكن ملاحظتها في السلوك.

على الفكرة العامة من جمع القمامة هو أنه ينبغي أن تجعل محاولة معقولة مؤكدا أن تخصيص الذاكرة سوف تنجح.للأسف انه من المستحيل أساسا إلى ضمان أن أي تخصيص الذاكرة سوف تنجح, حتى إذا كان لديك أحد هواة جمع القمامة في العملية.وهذا صحيح إلى حد ما في أي حال ، ولكن بشكل خاص في حالة C++ لأنها (ربما) لا يمكن استخدام نسخ جامع (أو أي شيء مشابه) التي تتحرك الكائنات في الذاكرة خلال مجموعة دورة.

إذا كنت لا تستطيع تحريك الأشياء, لا يمكنك إنشاء واحدة متجاورة مساحة الذاكرة التي لا المخصصات الخاصة بك -- وهذا يعني كومة الخاص بك (أو مخزن مجانا, أو ما كنت أفضل أن أسميها) ، وربما سوف تصبح مجزأة مع مرور الوقت.وهذا بدوره يمكن أن تمنع تخصيص من النجاح ، حتى عندما يكون هناك المزيد من الذاكرة مجانا من المبلغ المطلوب.

في حين أنه قد يكون من الممكن أن تأتي مع بعض ضمان أن يقول (في الجوهر) أنه إذا كرر بالضبط نفس النمط من توزيع مرارا وتكرارا, نجح في المرة الأولى ، وسوف تستمر في النجاح على التكرار اللاحقة شريطة أن الذاكرة المخصصة أصبح يتعذر الوصول إليها بين التكرارات.هذا ضعف نضمن انها عديمة الفائدة أساسا, ولكن لا أستطيع أن أرى أي أمل كبير في تعزيز ذلك.

حتى أنه أقوى ما اقترح C++.على المقترح السابق [تحذير:PDF] (التي حصل تراجع) لم يضمن أي شيء على الإطلاق.في 28 صفحة من اقتراح ماذا لديك في الطريق من الخارج يمكن ملاحظتها في سلوك واحد (غير المعيارية) ملاحظة تقول:

[ ملاحظة:القمامة التي تم جمعها برامج ذات جودة عالية استضافت التنفيذ ينبغي أن محاولة تحقيق أقصى قدر من الوصول الذاكرة فإنه يسترد.—end note ]

على الأقل بالنسبة لي, هذا يثير خطيرة سؤال حول العائد على الاستثمار.نحن ذاهبون لكسر رمز القائمة (لا أحد متأكد بالضبط كم لكن بالتأكيد قليلا جدا) ، وضع متطلبات جديدة على تطبيقات قيود جديدة على مدونة و ما نحصل عليه في المقابل هو تماما ربما لا شيء على الإطلاق ؟

حتى في أفضل ما لدينا هي البرامج التي ، على أساس اختبار مع جافا, ربما يتطلب حوالي ستة أضعاف الذاكرة لتشغيل في نفس السرعة يفعلون الآن.أسوأ جمع القمامة كان جزءا من جافا من البداية -- C++ أماكن كافية المزيد من القيود على جمع القمامة التي سوف يكاد يكون من المؤكد حتى أسوأ التكلفة/المنفعة نسبة (حتى إذا ذهبنا أبعد ما الاقتراح ضمان نفترض أنه سيكون هناك بعض المنافع).

أود تلخيص الوضع رياضيا:هذا الوضع المعقد.أي رياضيات يعلم عدد مركب من جزأين:الحقيقية والمتخيلة.يبدو لي أن ما لدينا هنا هي التكاليف الحقيقية ، ولكن الفوائد التي هي (على الأقل معظمهم) وهمي.

إذا كنت تريد التلقائي جمع القمامة ، هناك تجارية جيدة و المجال العام جامعي القمامة C++.للتطبيقات حيث جمع القمامة هو مناسبة, C++ ممتازة القمامة التي تم جمعها اللغة مع الأداء الذي يقارن ايجابيا مع غيرها من القمامة جمعت اللغات.انظر C++ لغة البرمجة (4rd طبعة) من أجل مناقشة التلقائي جمع القمامة في C++.انظر أيضا هانز J.بوهم هو موقع C و C++ جمع القمامة (أرشيف).

أيضا, C++ يدعم تقنيات البرمجة التي تسمح الذاكرة إدارة آمنة الضمني دون جمع القمامة.أنا أعتبر جمع القمامة آخر خيار ناقص طريقة التعامل مع إدارة الموارد.هذا لا يعني أبدا أنه من المفيد ، أن هناك أفضل النهج في كثير من الحالات.

المصدر: http://www.stroustrup.com/bs_faq.html#garbage-collection

أما لماذا لا يكون ذلك في بني ، إذا كنت أتذكر بشكل صحيح اخترع من قبل GC كان الشيء, وأنا لا أعتقد أن اللغة يمكن أن يكون قد GC لعدة أسباب(I. E إلى الوراء البرنامج متوافق مع C)

ويساعد هذا الأمل.

Stroustrup جعلت بعض تعليقات جيدة على هذا في عام 2013 سوف الأصلية المؤتمر.

فقط انتقل إلى حوالي 25m50s في هذا الفيديو.(أنصح بمشاهدة الفيديو كلها في الواقع ، ولكن هذا يتخطى إلى الكلام عن جمع القمامة.)

عندما يكون لديك حقا اللغة العظيمة التي تجعل من السهل (و آمن و يمكن التنبؤ بها ، سهلة القراءة وسهلة-إلى-تعليم) للتعامل مع الأشياء والقيم بطريقة مباشرة ، وتجنب (صريح) استخدام كومة الذاكرة المؤقتة, ثم أنت حتى لا تريد جمع القمامة.

مع الحديث C++ و الاشياء لدينا في C++11, جمع القمامة لم يعد مرغوبا فيه إلا في ظروف محدودة.في الواقع, حتى لو كان جيد جامع القمامة بنيت في واحدة من كبرى C++ compilers, أعتقد أنه لن يتم استخدامها في كثير من الأحيان.سيكون أسهل, وليس أصعب لتجنب GC.

يظهر هذا المثال:

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

هذا غير آمنة في C++.لكنه أيضا غير آمنة في جافا!في C++, لو ترجع الدالة في وقت مبكر ، delete سوف أبدا أن يسمى.ولكن إذا كان لديك كامل جمع القمامة ، مثل Java, كنت مجرد الحصول على اقتراح من أن الكائن سيتم دمر "في مرحلة ما في المستقبل" (تحديث: انها أسوأ من ذلك أن هذا.جافا لا لا وعد إلى استدعاء finalizer من أي وقت مضى - أنه ربما أبدا أن يسمى).هذا ليس جيدا بما فيه الكفاية إذا كان الأداة يحمل ملف مفتوح التعامل معها ، أو اتصال إلى قاعدة بيانات ، أو البيانات التي لديك مخزنة على الكتابة إلى قاعدة البيانات في وقت لاحق.نريد الأداة ليتم تدميرها بمجرد الانتهاء من ذلك ، من أجل تحرير هذه الموارد في أقرب وقت ممكن.كنت لا تريد الخاص بك ملقم قاعدة بيانات تكافح مع الآلاف من اتصالات قاعدة البيانات التي لم تعد مطلوبة - بل لا يعرف هذا البرنامج هو الانتهاء من العمل.

إذن ما هو الحل ؟ هناك عدد قليل من النهج.نهج واضح ، والتي سوف تستخدم الغالبية العظمى من الكائنات:

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 مرتين.والهدف هو تدمير في نهاية الدالة.إذا كان هذا هو ما تريد هذا هو بديهية جدا. Gadgets تتصرف نفس int أو double.يمكن التنبؤ به ، سهلة القراءة وسهلة-إلى-تعليم.كل شيء هو "القيمة".في بعض الأحيان قيمة كبيرة ، ولكن القيم أسهل لتعليم لأنك لا تملك هذا 'العمل على مسافة شيء أن تحصل مع مؤشرات (أو المراجع).

معظم الكائنات تقوم للاستخدام فقط في الوظيفة التي خلق لهم ، وربما مرت كمدخلات الطفل الوظائف.مبرمج لا يجب أن نفكر في 'إدارة الذاكرة' عند عودته الكائنات ، أو تبادل الأشياء عبر فصل على نطاق واسع في أجزاء من البرنامج.

نطاق مدى الحياة الهامة.أكثر من مرة, أنه من الأسهل إذا كان عمر هو نفس النطاق.فإنه من السهل أن نفهم و أسهل إلى تعليم.عندما تريد حياة مختلفة ، فإنه ينبغي أن يكون واضحا قراءة التعليمات البرمجية التي تفعل هذا عن طريق استخدام shared_ptr على سبيل المثال.(أو العودة (كبير) كائنات من قيمة الاستفادة من هذه الخطوة-دلالات أو unique_ptr.

قد يبدو هذا مثل الكفاءة المشكلة.ما إذا كنت ترغب في العودة أداة من foo()?C++11 تحرك دلالات تجعل من الأسهل العودة الأجسام الكبيرة.مجرد كتابة Gadget foo() { ... } وأنها سوف تعمل فقط ، والعمل بسرعة.أنت لا تحتاج إلى الفوضى مع && نفسك فقط عودة الأمور حسب القيمة اللغة غالبا ما تكون قادرة على القيام يلزم من تحسينات.(حتى قبل C++03, المجمعين لم ملحوظ في تجنب النسخ لا لزوم لها.)

كما Stroustrup وقال في مكان آخر في الفيديو (إعادة الصياغة): "فقط في عالم الكمبيوتر أن الإصرار على نسخ كائن ، ثم تدمير الأصلي.(الجمهور يضحك).لماذا لا مجرد نقل الكائن مباشرة إلى الموقع الجديد ؟ هذا ما البشر (وليس علماء الكمبيوتر) نتوقع."

عندما يمكنك أن تضمن نسخة واحدة فقط من الكائن المطلوب ، هو أسهل بكثير لفهم عمر من وجوه.يمكنك اختيار ما عمر السياسة تريد ، وجمع القمامة هناك إذا كنت تريد.ولكن عندما نفهم فوائد النهج الأخرى, ستجد أن جمع القمامة هو في الجزء السفلي من قائمة التفضيلات.

إذا كان هذا لا يعمل بالنسبة لك ، يمكنك استخدام unique_ptr, أو إذا تعذر ذلك ، shared_ptr.مكتوبة بشكل جيد C++11 أقصر وأسهل للقراءة و أسهل من تعليم العديد من اللغات الأخرى عندما يتعلق الأمر إلى إدارة الذاكرة.

الفكرة وراء C++ هو أنك لن تدفع أي تأثير الأداء الميزات التي لا تستخدمها.إضافة لذلك جمع القمامة قد يعني وجود بعض برامج تشغيل مباشرة على الأجهزة الطريق C وبعض ضمن نوعا من وقت تشغيل الجهاز الظاهري.

لا شيء يمنعك من استخدام بعض شكل من المؤشرات الذكية التي ترتبط بعض طرف ثالث آلية لجمع القمامة.أذكر Microsoft تفعل شيئا مثل COM و لم يذهب جيدا.

الإجابة على معظم أسئلة "لماذا" حول C++, قراءة تصميم وتطور C++

لأن الحديث C++ لا تحتاج إلى جمع القمامة.

Bjarne Stroustrup التعليمات الجواب على هذه المسألة يقول:

أنا لا أحب القمامة.أنا لا أحب رمي النفايات.بلدي المثالي هو القضاء على الحاجة إلى جمع القمامة من قبل لا تنتج أي القمامة.هذا هو الممكن الآن.


الوضع على قانون مكتوب في هذه الأيام (C++17 وبعد الرسمية المبادئ التوجيهية الأساسية) على النحو التالي:

  • معظم الذاكرة ملكية التعليمات البرمجية ذات الصلة في المكتبات (وخاصة توفير حاويات).
  • معظم استخدام من التعليمات البرمجية التي تنطوي على الذاكرة ملكية يتبع RAII نمط, لذا تم تخصيص على البناء deallocation على الدمار الذي يحدث عند الخروج من نطاق في أي شيء كان المخصصة.
  • لك لا صراحة تخصيص أو إلغاء تخصيص الذاكرة مباشرة.
  • الخام المؤشرات لا تملك الذاكرة (إذا كنت قد اتبعت المبادئ التوجيهية) ، لذلك لا يمكن أن تسرب عن طريق تمرير لهم في جميع أنحاء.
  • إذا كنت أتساءل كيف أنت ذاهب لتمرير بدءا من عناوين تسلسل القيم في الذاكرة - عليك أن تفعل ذلك مع span;لا الخام المؤشر المطلوبة.
  • إذا كنت حقا بحاجة إلى امتلاك "مؤشر" ، يمكنك استخدام C++' معيار-مكتبة المؤشرات الذكية - لا يمكن أن تسرب و هي فعالة جدا.بدلا من ذلك, يمكنك تمرير الملكية عبر نطاق الحدود مع "مالك مؤشرات".هذه ليست شائعة ويجب أن تستخدم بوضوح ؛ وأنها تسمح الجزئي ثابت فحص ضد تسرب.

"أوه نعم ؟ ولكن ماذا عن...

...إذا أنا فقط أكتب رمز الطريقة التي تستخدم لكتابة C++ في الأيام الخوالي؟"

في الواقع ، يمكن أن فقط تجاهل كل من المبادئ التوجيهية كتابة راشح رمز التطبيق سوف ترجمة وتشغيل (وتسرب), كما هو الحال دائما.

ولكن ليس "لا تفعل ذلك" الوضع ، حيث المطور من المتوقع أن تكون فاضلة و ممارسة الكثير من الرقابة الذاتية;انها فقط لا أبسط إلى كتابة غير مطابقة رمز ، كما أنها أسرع في الكتابة ، ولا هو الأفضل أداء.تدريجيا سوف تصبح أكثر صعوبة الكتابة, كما أنك ستواجه زيادة "مقاومة عدم التوافق" مع ما تتفق ينص القانون وتتوقع.

...إذا كنت reintrepret_cast?أو القيام مؤشر الحساب ؟ أو غيرها من مثل هذه الخارقة؟"

في الواقع, إذا كنت وضعت عقلك إلى ذلك ، يمكنك كتابة التعليمات البرمجية التي تفسد الأمور على الرغم من اللعب الجميل مع المبادئ التوجيهية.ولكن:

  1. يمكنك أن تفعل هذا نادرا (من حيث الأماكن في القانون ، ليس بالضرورة من حيث جزء من وقت التنفيذ)
  2. كنت فقط تفعل هذا عمدا وليس عن طريق الخطأ.
  3. وبذلك سوف تبرز في برنامج يتوافق مع المبادئ التوجيهية.
  4. انها نوع من التعليمات البرمجية التي من شأنها تجاوز GC في لغة أخرى على أي حال.

...مكتبة التنمية؟"

إذا كنت C++ مكتبة المطور ثم فعل كتابة تعليمات برمجية غير آمنة تشمل الخام المؤشرات ، هل هناك حاجة إلى رمز بعناية ومسؤولية - ولكن هذه هي بذاتها قطعة من التعليمات البرمجية التي كتبها خبراء (والأهم من ذلك ، استعرض الخبراء).


هكذا, انها مجرد مثل Bjarne قال:هناك حقا أي الدافع لجمع القمامة بشكل عام ، ولكن تأكد من عدم إنتاج القمامة.GC أصبحت غير مشكلة مع C++.

هذا لا يعني GC ليست مشكلة مثيرة للاهتمام لبعض تطبيقات محددة ، عندما تريد أن توظف مخصص توزيع دي-مخصصات الاستراتيجيات.بالنسبة لأولئك كنت تريد مخصص توزيع دي-تخصيص لغة على مستوى GC.

أحد المبادئ الأساسية وراء الأصلي لغة C هو أن الذاكرة تتألف من سلسلة من البايتات ، رمز تحتاج فقط يهتمون بما أولئك بايت يعني في نفس اللحظة التي يتم استخدامها.الحديث C يسمح المجمعين إلى فرض قيود إضافية ، ولكن ج يشمل-و C++ يحتفظ--القدرة على تتحلل مؤشر إلى سلسلة من البايتات, تجميع أي تسلسل بايت تحتوي على نفس القيم في المؤشر ، ثم استخدام هذا المؤشر إلى الوصول في وقت سابق الكائن.

في حين أن القدرة يمكن أن تكون مفيدة أو حتى التي لا غنى عنها-في بعض أنواع التطبيقات, لغة تتضمن هذه القدرة سوف تكون محدودة جدا في قدرته على دعم أي نوع من مفيد وموثوق بها جمع القمامة.إذا كان المترجم لا يعرف كل ما تم القيام به مع الأجزاء التي تتكون مؤشر, سيكون لديك أي وسيلة لمعرفة ما إذا كانت المعلومات كافية لإعادة بناء المؤشر قد تكون موجودة في مكان ما في الكون.لأنه سيكون من الممكن أن المعلومات المخزنة بطرق الكمبيوتر لن تكون قادرة على الوصول حتى لو كان يعرف عنهم (مثلا ، وحدات البايت التي تشكل المؤشر قد تظهر على الشاشة لفترة طويلة بما فيه الكفاية لشخص ما أن كتابتها على قطعة من الورق) ، قد يكون من المستحيل حرفيا على الكمبيوتر لمعرفة ما إذا كان مؤشر يمكن استخدامها في المستقبل.

مثيرة للاهتمام شاءت من العديد من القمامة التي تم جمعها أطر هو كائن مرجع لم يحددها بعض أنماط الواردة فيه ، ولكن من خلال العلاقة بين البتات التي عقدت في مرجع كائن وغيرها من المعلومات التي عقدت في أماكن أخرى.في C و C++ ، إذا بت نمط المخزنة في مؤشر يحدد كائن ، هذا جزء من نمط تحديد هذا الكائن إلى كائن صراحة تدميرها.في نموذجي GC نظام كائن قد تكون ممثلة قليلا نمط 0x1234ABCD في لحظة واحدة في الوقت ، GC دورة قد تحل محل جميع الإشارات إلى 0x1234ABCD مع إشارات إلى 0x4321BABE ، وعندها لن يكون الكائن الذي يمثله النمط الأخير.حتى لو كان واحد لعرض بت نمط المرتبطة مرجع كائن ثم قراءتها مرة أخرى من لوحة المفاتيح ، لن يكون هناك أي توقع أن نفس الشيء نمط يمكن استخدامها لتحديد نفس الكائن (أو أي كائن).

كل التقني الحديث هو overcomplicating مفهوم.

إذا وضعت GC في C++ لجميع الذاكرة تلقائيا ثم النظر في ما يشبه متصفح الويب.مستعرض ويب يجب تحميل كامل الوثيقة على شبكة الإنترنت وتشغيل البرامج النصية على شبكة الإنترنت.يمكنك تخزين ويب النصي المتغيرات في الوثيقة شجرة.في الوثيقة في المتصفح مع الكثير من علامات التبويب المفتوحة ، فهذا يعني أن في كل مرة GC يجب أن تفعل مجموعة كاملة كما يجب مسح جميع عناصر المستند.

على معظم أجهزة الكمبيوتر وهذا يعني أن صفحة أخطاء تحدث.لذلك السبب الرئيسي الإجابة على السؤال هو أن أخطاء الصفحات سوف تحدث.سوف تعرف هذا عندما يبدأ جهاز الكمبيوتر الخاص بك مما يجعل الكثير من الوصول إلى القرص.وذلك لأن GC يجب أن تلمس الكثير من الذاكرة من أجل إثبات باطل المؤشرات.عندما يكون لديك حسن النية تطبيق استخدام الكثير من الذاكرة ، الحاجة إلى مسح كافة الكائنات في كل مجموعة فسادا بسبب أخطاء الصفحات.صفحة خطأ عندما الذاكرة الظاهرية يحتاج الى الحصول على قراءة مرة أخرى من القرص إلى ذاكرة الوصول العشوائي.

وبالتالي فإن الحل الصحيح هو تقسيم التطبيق إلى الأجزاء التي تحتاج GC والأجزاء التي لا.في حالة من متصفح الويب المثال أعلاه ، إذا كان المستند شجرة تم تخصيص مع malloc ، ولكن جافا سكريبت ركض مع GC, ثم في كل مرة GC في ركلات فقط بمسح جزء صغير من الذاكرة ، كل تقسيم عناصر الذاكرة الوثيقة الشجرة لا تحتاج إلى الحصول على ترحيلها مرة أخرى.

لمزيد من فهم هذه المشكلة تبدو على الذاكرة الظاهرية وكيفية تطبيقه في أجهزة الكمبيوتر.ذلك هو كل شيء عن حقيقة أن 2GB يتوفر البرنامج عندما لم يكن هناك حقا الكثير من ذاكرة الوصول العشوائي.على أجهزة الكمبيوتر الحديثة مع 2GB من ذاكرة الوصول العشوائي على نظام 32BIt أنه ليست هذه مشكلة بشرط واحد فقط تشغيل البرنامج.

كما إضافي سبيل المثال ، تعتبر مجموعة كاملة التي يجب أن تتبع جميع الكائنات.أولا يجب أن تفحص جميع الكائنات يمكن الوصول إليها عن طريق الجذور.الثاني مسح كافة الكائنات مرئية في الخطوة 1.ثم مسح انتظار المتلفات.ثم انتقل إلى جميع الصفحات مرة أخرى وإيقاف جميع الكائنات غير مرئية.وهذا يعني أن العديد من الصفحات قد تحصل على تبديل الخروج والعودة في أوقات متعددة.

لذا جوابي لتحقيق ذلك هو أن عدد أخطاء الصفحات التي تحدث نتيجة لمس كل ذكرى أسباب GC الكامل لجميع الكائنات في البرنامج أن تكون غير مجدية و لذلك يجب على مبرمج عرض GC كعامل مساعد أشياء مثل البرامج النصية و بيانات العمل, ولكن هل الأمور العادية مع دليل إدارة الذاكرة.

والآخر سبب مهم جدا من دورة المتغيرات العالمية.في جامع أن نعرف أن متغير عمومي المؤشر في GC ذلك يتطلب كلمات رئيسية محددة ، وبالتالي الموجودة C++ الكود لن يعمل.

الجواب القصير:نحن لا نعرف كيف نفعل جمع القمامة بكفاءة (مع قاصر الزمان والمكان النفقات العامة) بشكل صحيح في كل وقت (في جميع الحالات الممكنة).

الجواب طويل:تماما مثل C, C++ هي أنظمة اللغة ؛ هذا يعني أنها تستخدم عند كتابة رمز نظام مثل نظام التشغيل.وبعبارة أخرى, C++ تصميم مثل C, مع أفضل الممكن الأداء كهدف رئيسي.اللغة القياسية لن تضيف أي الميزة التي قد تعيق أداء الهدف.

هذا يتوقف على السؤال:لماذا جمع القمامة يعيق الأداء ؟ والسبب الرئيسي هو أنه عندما يتعلق الأمر بالتنفيذ ، نحن [علماء الكمبيوتر] لا أعرف كيف أفعل جمع القمامة مع الحد الأدنى من النفقات العامة في جميع الحالات.وبالتالي من المستحيل أن برنامج التحويل البرمجي C++ و وقت تشغيل النظام لأداء جمع القمامة بكفاءة في كل وقت.من ناحية أخرى, C++ مبرمج, يجب أن تعرف له تصميم/تنفيذ و هو أفضل شخص يقرر كيفية القيام جمع القمامة.

الماضي, إذا كان التحكم (الأجهزة, تفاصيل, الخ.) والأداء (وقت, فضاء, قوة, الخ.) ليست القيود الرئيسية ، ثم C++ ليست الكتابة أداة.لغة أخرى قد تكون أفضل وتقديم المزيد من [خفية] runtime الإدارة ، مع ما يلزم من النفقات العامة.

عند مقارنة C++ Java, يمكنك ان ترى على الفور أن C++ ليست مصممة مع الضمني جمع القمامة في الاعتبار ، في حين كان جافا.

وجود أشياء مثل التعسفي المؤشرات في ج-أسلوب القطعية المتلفات لا تبطئ أداء GC-تطبيقات ، فإنه أيضا تدمير التوافق على كمية كبيرة من C++-تراث-رمز.

بالإضافة إلى ذلك, C++ هي اللغة التي تهدف إلى تشغيل مستقل قابل للتنفيذ بدلا من وجود مجمع بيئة وقت التشغيل.

جميع في كل شيء:نعم كان من الممكن لإضافة جمع القمامة إلى C++, ولكن من أجل استمرارية فمن الأفضل عدم القيام بذلك.تكلفة القيام بذلك سيكون أكبر من الفائدة.

أساسا لسببين:

  1. لأنه لا حاجة واحدة (IMHO)
  2. لأنه الى حد كبير يتنافى مع RAII الذي هو حجر الزاوية في C++

C++ بالفعل يقدم دليل إدارة الذاكرة تخصيص مكدس, RAII, حاويات, التلقائي المؤشرات المؤشرات الذكية...وينبغي أن يكون كافيا.جامعي القمامة هي كسول المبرمجين الذين لا تريد أن تنفق 5 دقائق التفكير الذي يجب أن تملك أي كائنات أو عندما يجب أن الموارد سراحهم.هذا ليس كيف نفعل الأشياء في C++.

فرض جمع القمامة هو حقا مستوى منخفض إلى مستوى عال نقلة نوعية.

إذا نظرتم إلى الطريقة التي يتم مناولة الجمل في اللغة جمع القمامة ، سوف تجد أنها تسمح فقط مستوى عال وظائف معالجة سلسلة و لا تسمح الثنائية الوصول إلى سلاسل.ببساطة, كل وظائف سلسلة أولا التحقق من مؤشرات لمعرفة أين السلسلة ، حتى لو كنت فقط رسم بايت.حتى إذا كنت تفعل حلقة العمليات كل بايت في سلسلة في اللغة جمع القمامة ، فإنه يجب حساب قاعدة الموقع بالإضافة إلى إزاحة كل تكرار, لأنه لا يمكن معرفة متى السلسلة انتقلت.ثم عليك أن تفكر في أكوام أكوام, المواضيع, الخ الخ.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top