لماذا هو أنه من المستحيل أن يكون إشارة إلى الفراغ ؟

StackOverflow https://stackoverflow.com/questions/457896

  •  19-08-2019
  •  | 
  •  

سؤال

لماذا هو أنه من المستحيل أن يكون إشارة إلى الفراغ ؟ الشيء الوحيد الذي وجدته في C++ القياسية هو هذا الخط ، 8.3.2.1

أ declarator التي تحدد نوع "إشارة إلى السيرة الذاتية الفراغ" هو سوء تشكيلها.

لماذا هو هكذا ؟ لماذا لا أستطيع كتابة "عامة" وظيفة قبول void&?

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


لتوضيح قليلا, أنا أفهم أن استخدام إشارة إلى الفراغ "كما هي" سيكون بلا معنى كما dereferencing مؤشر إلى الفراغ.ومع ذلك ، يمكن أن يلقي ذلك إشارة إلىsometype من أجل استخدام ذلك, أليس كذلك ؟ في الواقع, أنا لا أرى لماذا المقتطف التالي يمكن العمل...

void foo(void *data)
{
    int *i = reinterpret_cast<int*>(data);
    // do something with i
}

...في حين أن هذا لا يمكن للمرء أن:

void foo(void &data)
{
    int &i = reinterpret_cast<int&>(data);
    // do something with i
}
هل كانت مفيدة؟

المحلول

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

"الفراغ" اثنين من الاستخدامات:إلى نفي أي معرفة نوع (كما في الفراغ *) ، وتحديد أي شيء مقابل شيء (وظيفة الفراغ العودة).في حالة لا هل من الممكن أن أقول أي شيء عن الفراغ شيئا إلا أنه قد يكون لها عنوان.

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

نصائح أخرى

اسأل نفسك أولا كيف دي-مرجع الفراغ المؤشر ؟

void *p = /*something*/ ;
cout << *p << endl;

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

في إشارة إلى الفراغ sufferes من نفس المشكلة ، تعريف البيانات إلى أن لا يكون نوع, وبالتالي لا يمكن الرجوع إليها في أي طريقة مجدية.

أن مرجع ذلك لك - مبرمج - تحتاج إلى الزهر إلى نوع آخر, ثم هل يمكن أن يكون كتبته الإشارة إلى ذلك.

لست متأكدا إذا كنت شرحت هذا كما أردت.

روبن, أي أفكار ؟

تحرير: للإجابة على تحرير الخاص بك.

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

logger << data;

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

void* data = /* some assignment */;
logger << *data; // compiler error.

الآن المترجم لن تسمح لك إلغاء مرجعية الفراغ* لأي سبب من الأسباب (لا معنى له) ، نفس تقف على إشارة إلى الفراغ &البيانات باستثناء ذلك لأنه مرجع إنه ضمنا dereferenced في كل وقت.المترجم لن تسمح لك إلغاء مرجعية الفراغ* على عملية واحدة ، انها لن تسمح لك إلغاء مرجعية باستمرار.

void& data = /* some assignment *.;
logger << data; // means same as logger << *data above

لا يمكنك أن تفعل أي شيء البيانات إلا أعتبر عنوان و هناك طريقة جيدة و آمنة - طريقة بنيت في لغة للقيام بذلك ، أي

void* data;

هذا يجعل أي معنى ؟

الإشارة هي إشارة إلى مثيل في شيء.مثيل من شيء لا يمكن أن يكون من نوع void.أي مثيل من شيء يجب أن يكون نوع معين (وربما قاعدة أنواع).

هنا ملخص من الأشياء المختلفة التي تم قال: وأنا أفكر.

سببان رئيسيان الإشارة إلى الفراغ مسموح


1 أنها كانت عديمة الفائدة تماما.

في الواقع, إذا نظرنا إلى الوراء في أوقات C, الفراغ مؤشرات تحقيق غرضين هما:

  • إدارة الذاكرة (مثلا ، malloc)
  • Genericity (كتابة الوظائف التي يمكن أن تقبل أي نوع من الحجج)

عندما C++ خرج قوالب أصبح الحل الأفضل لتنفيذ genericity.بيد أن العرف إدارة الذاكرة كان لا يزال ممكنا ، التوافقية بين C++ و C مصدر قلق كبير ، لذلك الفراغ* كان keeped.وهي افتراضية الفراغ المرجعي أن يكون من أي مساعدة مع إدارة الذاكرة ، genericity هو غطت بالفعل ، وذلك أساسا قد لا فائدة تقريبا (باستثناء ضمان عدم nullness هو موضح أدناه).

2 أنت لن تكون قادرة على فعل أي شيء معها

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

void *data = // something
// using *data and data-> is forbidden

void &data = // something
// using data is forbidden

ومع ذلك يمكننا التفكير في استخدام حالة الإشارة لا يجب أن يكون "dereferenced" (هذه العبارة بفظاعة غير صحيحة, ولكن يمكنك الحصول على وجهة نظري) ولكن أين نحن لن يستغرق سوى عنوانه .دعونا نفترض أن لدي الدالة التالية:

void foo(void *dataptr)
{
    assert(dataptr != NULL); // or != 0
    // do something with dataptr
}

لتجنب هذا مزعج تأكيد يمكنني كتابة الدالة على هذا النحو:

void foo(void &dataref)
{
    void *data = &dataref;
    // do something with data
}

ومع ذلك ، لهذا العمل ، &dataref يحتاج إلى ما يعادل dataptr, الذي ليس هو الحال: &dataref ما يعادل &*dataptr!

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

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

حسنا, هناك شيء واحد يزعجني حول هذا الموضوع.فكرة void*, كما ذكر أعلاه, أنه لا يزال ساري المفعول متغير يحتوي على عنوان ، ولكن نوع يتم تجاهلها.هذا يبدو المسموح به وبما أننا يمكن أن لا تزال تعمل مع بيانات العنوان - نوع إلى حد ما زائدة (أو أقل أهمية) في هذا السياق.Dereferencing أنها سيئة ، بسبب محاولة الوصول إلى الأعضاء لا يعقل مثلا p.mem.نحن لا نعرف ماذا الصف للإشارة إلى ، وبالتالي فإن الذاكرة للقفز ، vtable مؤشرات لمتابعة.

ومع ذلك, انها تريد ثم يبدو من المنطقي أن p من تلقاء نفسها أن تكون على ما يرام منذ أن تشير فقط إلى كائن ، ولكن أيا من البيانات.لا فئة المعلومات اللازمة للقيام بذلك فقط العنوان.أنا أفهم أن هناك على الإطلاق أي استخدام لهذا, ولكن من المهم في تحديد عندما تتعطل الأمور.يسمح هذا المفهوم, C++ المرجعية (باستمرار dereferenced ولكن ليس في الوصول إلى أي شيء) على سبيل المثال void& ref = static_cast< &void >(obj) أيضا معنى ، وبالتالي تسمح الفراغ المراجع.أنا لا أقول أي شخص يجب أن تأخذ هذا الأمر مع المسؤولين ، ولكن من "الشعور" وجهة نظر ، يبدو الصحيح ؟

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

أن أي شخص تتفق مع ذلك ؟

يمكنك التفكير في إشارة دي المشار إليها المؤشر.نحويا تعامل المرجعية كما لو أنها ليست مؤشر:لا تحتاج * مشغل dereference ذلك ، يمكنك استخدام .بدلا من -> الوصول إلى أعضائها.

ومع ذلك ، لا يمكنك إلغاء مرجعية a void مؤشر.كما أشار الثنائية القلق تحاول أن تفعل ذلك سوف يعطيك خطأ برنامج التحويل البرمجي.و إذا كنت لا يمكن أن يكون dereferenced الفراغ المؤشر هذا يعني أنك لا يمكن أن يكون إشارة باطلة.

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

ومن المسلم به أنه لا يزال من الممكن الإشارة إلى الرجوع إلى كائن لا وجود بعد الآن, ولكن هذا هو الاستثناء.

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

بلدي الشركة كان واحدا من أول استخدام C++ تجاريا في البداية تجميعها باستخدام Cfront.أوائل المطورين لا تزال تعلم اللغة ، و عموما استخدام كل خدعة في الكتاب (المشغلين في كل مكان!).هنا هو خدعة ظنوا أنه cool:

void Foo::something(int action, ostream &os = *(ostream *)0)
{
   ostream *os_p = &os;
   if (&os == (ostream *)0) {
      os_p = &cerr;
   }
   // continue with method
}

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

الفراغ هو شيء, بحكم التعريف, لا وجود لها, لذلك ليس من المنطقي أن يكون ذلك في العنوان.

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