سؤال

هذا هو السؤال الذي كان يزعجني لبعض الوقت.اعتقدت دائمًا أنه يجب تصميم لغة C++ بحيث يعمل عامل التشغيل "الحذف" (بدون الأقواس) حتى مع عامل التشغيل "الجديد []".

في رأيي أن أكتب هذا:

int* p = new int;

يجب أن يكون معادلاً لتخصيص مجموعة من عنصر واحد:

int* p = new int[1];

إذا كان هذا صحيحًا، فمن الممكن دائمًا أن يقوم عامل "الحذف" بحذف المصفوفات، ولن نحتاج إلى عامل التشغيل "delete[]".

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

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

المحلول

وانها بحيث تالفة من العناصر الفردية سوف يتم استدعاؤها. نعم، للصفائف القرون، وليس هناك الكثير من الفرق، ولكن في C ++، هل يمكن أن يكون صفائف الكائنات مع تالفة غير تافهة.

والآن، سؤالك هو، لماذا لا تجعل new وdelete تتصرف مثل new[] وdelete[] والتخلص من new[] وdelete[]؟ أود أن أعود "تصميم وتطور" Stroustrup كتاب حيث قال أنه إذا كنت لا تستخدم ميزات C ++، يجب أن لا تضطر لدفع لهم (في وقت التشغيل على الأقل). الطريقة التي تقف الآن، فإن new أو delete تتصرف بكفاءة كما malloc وfree. إذا كان delete معنى delete[]، سيكون هناك بعض الحمل الزائد في وقت التشغيل (كما أشار جيمس كوران الخروج).

نصائح أخرى

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

وجوابي الأصلي (الذي يفتقد نقطة واحدة) ::

و"حذف" حذف كائن واحد. "حذف []" حذف مجموعة الكائن. لحذف [] للعمل، وتنفيذ يحافظ على عدد من العناصر في المصفوفة. أنا فقط انقر نقرا مزدوجا التحقق من هذا من قبل تصحيح التعليمات البرمجية ASM. في تنفيذ (VS2005) اختبرت، تم تخزين عدد كبادئة إلى مجموعة الكائن.

إذا كنت تستخدم "حذف []" على كائن واحد، ومتغير عدد القمامة حتى تعطل التعليمات البرمجية. إذا كنت تستخدم "حذف" لمجموعة وجوه، بسبب بعض التناقض، تعطل التعليمات البرمجية. اختبرت هذه الحالات فقط الآن!

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

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

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

والشيء الوحيد الذي يمكنني أن أفكر في أن هناك القليل جدا من الحمل الزائد لعلاج كائن واحد كصفيف (وهي "for(int i=0; i<1; ++i)" لا لزوم لها)

وإضافة هذا لأنه لا إجابة أخرى يتناول أنه حاليا:

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

struct Base { virtual ~Base(); };
struct Derived : Base { };
int main(){
    Base* b = new Derived;
    delete b; // this is good

    Base* b = new Derived[2];
    delete[] b; // bad! undefined behavior
}

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

int main(){
    int * p = new int;
    delete p; // cheap operation, no dynamic dispatch, no conditional branching
}

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

مارشال كلاين لديه بعض معلومات حول هذا الموضوع.

وdelete [] يضمن أن المدمر لكل فرد من أفراد ما يسمى (إن وجدت لنوع)، في حين delete فقط حذف الذاكرة المخصصة للمجموعة.

وفيما يلي قراءة جيدة: HTTP: //www.informit. كوم / أدلة / content.aspx؟ ز = cplusplus وseqNum = 287

<ديل> وهناك، والأحجام مجموعة لا يتم تخزين أي مكان في C ++. (شكرا للجميع لافتا إلى أن هذا البيان غير دقيق).

وأنا قليلا الخلط من جانب الجواب هارون وأعترف بصراحة أنا لا أفهم تماما لماذا وأين حذف [] هو مطلوب.

وفعلت بعض التجارب مع نموذج التعليمات البرمجية له (بعد إصلاح بعض الأخطاء المطبعية). وهنا النتائج بلدي.     الأخطاء المطبعية: ~ قاعدة في حاجة إلى وظيفة الجسم     أعلن قاعدة * ب مرتين

struct Base { virtual ~Base(){ }>; };
struct Derived : Base { };
int main(){
Base* b = new Derived;
delete b; // this is good

<strike>Base</strike> b = new Derived[2];
delete[] b; // bad! undefined behavior
}

وتجميع وتنفيذ

david@Godel:g++ -o atest atest.cpp 
david@Godel: ./atest 
david@Godel: # No error message

وبرنامج التعديل مع حذف [] إزالة

struct Base { virtual ~Base(){}; };
struct Derived : Base { };

int main(){
    Base* b = new Derived;
    delete b; // this is good

    b = new Derived[2];
    delete b; // bad! undefined behavior
}

وتجميع وتنفيذ

david@Godel:g++ -o atest atest.cpp 
david@Godel: ./atest 
atest(30746) malloc: *** error for object 0x1099008c8: pointer being freed was n
ot allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

وبطبيعة الحال، أنا لا أعرف ما إذا حذف [] ب تعمل فعلا في المثال الأول. أنا أعرف فقط أنه لا يعطي رسالة خطأ المترجم.

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