ধ্বংসকারী মধ্যে অদ্ভুত এনাম


83

বর্তমানে, আমি সোর্স কোড পড়া করছি Protocol Buffer, এবং আমি পাওয়া এক অদ্ভুত enumকোড সংজ্ঞায়িত এখানে

  ~scoped_ptr() {
    enum { type_must_be_complete = sizeof(C) };
    delete ptr_;
  }

  void reset(C* p = NULL) {
    if (p != ptr_) {
      enum { type_must_be_complete = sizeof(C) };
      delete ptr_;
      ptr_ = p;
    }
  }

কেন enum { type_must_be_complete = sizeof(C) };এখানে সংজ্ঞায়িত করা হয়? এটা কি কাজে লাগে?


4
যদি আমি হতে চাই যে নিশ্চিত, তারপর আমি বরং ব্যবহার করতে চাই ptr_নিজেই sizeofযেমন sizeof(*ptr_)পরিবর্তে sizeof(C)
নওয়াজ

উত্তর:


81

এই কৌশলটি ইউবিটিকে এড়িয়ে চলেছে যখন এই ধ্বংসকারী সংকলন করা হয় তখন সি এর সংজ্ঞা উপলব্ধ থাকে তা নিশ্চিত করে। অন্যথায় সংকলনটি sizeofঅসম্পূর্ণ প্রকার (ফরোয়ার্ড ঘোষিত প্রকারগুলি) নির্ধারণ করা যায়নি তবে পয়েন্টারগুলি ব্যবহার করা যেতে পারে।

সংকলিত বাইনারিতে, এই কোডটি অপ্টিমাইজ হবে এবং কোনও প্রভাব ফেলবে না।

দ্রষ্টব্য: অসম্পূর্ণ প্রকারটি মোছা 5.3.5 / 5 থেকে অপরিবর্তিত আচরণ হতে পারে : .

যদি মুছে ফেলা হচ্ছে এমন অবজেক্টের মুছে ফেলার সময় অসম্পূর্ণ শ্রেণীর ধরণ থাকে এবং সম্পূর্ণ শ্রেণিতে একটি তুচ্ছ ত্রুটিযুক্ত ডেস্ট্রাক্টর বা একটি অবনতি ফাংশন থাকে, আচরণটি অনির্ধারিত

g++ এমনকি নিম্নলিখিত সতর্কতা জারি করে:

সতর্কতা: মুছে ফেলা অপারেটরের অনুরোধে সম্ভাব্য সমস্যা সনাক্ত করা হয়েছে:
সতর্কতা: 'পি' এর অসম্পূর্ণ প্রকারের
সতর্কতা রয়েছে: 'স্ট্রাক্ট সি' এর সামনের ঘোষণা


4
"অসম্পূর্ণ প্রকারটি মুছে ফেলা অপরিজ্ঞাত আচরণ" ভুল is এটি কেবলমাত্র ইউবি যদি টাইপটির একটি তুচ্ছ ত্রুটিযুক্ত ডেস্ট্রাক্টর থাকে। এই ছোট্ট কৌশলটি যে সমস্যাটিকে সম্বোধন করে তা হ'ল এই যে অসম্পূর্ণ প্রকারটি মুছে ফেলা সর্বদা ইউবি হয় না , যাতে ভাষা এটি সমর্থন করে।
চিয়ার্স এবং এইচটিএইচ - Alf

ধন্যবাদ @ চিয়ারসান্থথ।-আলফ আমার বক্তব্যটি এটি ইউবি হতে পারে, তাই সাধারণভাবে কোডের এই লাইনটি ইউবি হয়। সম্পাদিত।
মোহিত জৈন

32

sizeof(C)সম্পূর্ণ টাইপ না হলে সংকলন সময়ে ব্যর্থ হবে Cenumএটিতে একটি স্থানীয় সুযোগ নির্ধারণ করা রানটাইম সময় বিবৃতিটিকে সৌম্য করে তোলে।

এটি প্রোগ্রামারটির নিজের থেকে নিজেকে রক্ষা করার একটি উপায়: delete ptr_অসম্পূর্ণ প্রকারের পরে এর আচরণটি অপরিজ্ঞাত হয় যদি এর মধ্যে একটি তুচ্ছ ত্রুটিযুক্ত ডেস্ট্রাক্টর থাকে।


4
আপনি কেন ব্যাখ্যা করতে পারবেন যে কেন সেই সময়ে সিটিকে একটি সম্পূর্ণ ধরণের হতে হবে - এটির জন্য সম্পূর্ণ টাইপ সংজ্ঞা deleteথাকা দরকার কি? এবং যদি তাই হয় তবে সংকলক কেন এটি ধরবে না?
পিটার হুল

4
এটা বরং এড়ানো সম্পর্কে নয় C = void? যদি Cনিছক কোনও অপরিজ্ঞাত প্রকার হয়, তবে কি deleteবিবৃতিটি ইতিমধ্যে ব্যর্থ হবে না ?
কেরেক এসবি

4
দেখে মনে হচ্ছে উত্তর পেয়েছে মোহিত জৈন।
পিটার হাল

4
.1 "এটিতে একটি স্থানীয় স্কোপ এনাম সেট করা স্টেটমেন্টটি রানটাইমে সৌম্য করে তোলে।" হ'ল, আহ, অর্থহীন। আমি দুঃখিত.
চিয়ার্স এবং এইচটিএইচ - আলফ

4
@ স্টিভ জেসপ ধন্যবাদ আমি যে অংশটি অনুপস্থিত ছিল তা হ'ল একটি অসম্পূর্ণ প্রকারটি মোছা হ'ল ইউবি।
পিটার হুল

28

এটি বুঝতে enum, এটি ছাড়া বিনষ্টকারী বিবেচনা করে শুরু করুন:

~scoped_ptr() {
    delete ptr_;
}

যেখানে ptr_একটি হল C*। যদি টাইপ Cএই সময়ে অসম্পূর্ণ, অর্থাত্ যে সব কম্পাইলার জানে struct C;তারপর, (1) একটি ডিফল্ট-জেনারেট do-কিছুই বিনাশকারী সি উদাহরণস্বরূপ ব্যবহার করা হয় দিকে ইঙ্গিত করলেন। কোনও স্মার্ট পয়েন্টার দ্বারা পরিচালিত কোনও সামগ্রীর জন্য এটি সঠিক জিনিস হওয়ার সম্ভাবনা কম।

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

একটি সম্পূর্ণ টাইপ একটি জ্ঞাত আকার আছে, এবং তাই, একটি সম্পূর্ণ টাইপ sizeof(C)হলে এবং শুধুমাত্র Cপরিচিত সংঘটিতকারীর সাথে সংকলন করবে । সুতরাং এটি প্রহরী হিসাবে ব্যবহার করা যেতে পারে। একটি উপায় সহজ হবে

(void) sizeof(C);  // Type must be complete

আমি অনুমান করব যে কয়েকটি সংকলক এবং বিকল্পগুলির সাহায্যে সংকলকটি এটি সংকলন করা উচিত নয় এবং এটি enumযে এইরকম-অনুসারী সংযোজক আচরণটি এড়াতে পারে তা দেখার আগে এটি অপসারণ করে:

enum { type_must_be_complete = sizeof(C) };

enumকেবল একটি প্রত্যাখ্যানিত প্রকাশের চেয়ে পছন্দের বিকল্প বিকল্পটি কেবল ব্যক্তিগত পছন্দ।

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


(1) অসম্পূর্ণ প্রকারের জন্য ডিফল্ট-উত্পন্ন ডু-নাথ ডেস্ট্রাক্টর পুরানো সমস্যা ছিল std::auto_ptr। এটি এত কুখ্যাত ছিল যে এটি পিআইএমপিএল আইডিয়ম সম্পর্কে একটি জিওটিডাব্লু আইটেমটিতে প্রবেশ করেছিল, এটি আন্তর্জাতিক সি ++ মানককরণ কমিটির সভাপতি হার্ব সটারের চেয়ার দ্বারা লেখা। অবশ্যই, আজকাল যেটি std::auto_ptrঅবহেলা করা হয়েছে, তার পরিবর্তে কেউ কেউ অন্য কোনও প্রক্রিয়া ব্যবহার করবে।


4
এনাম সংকলন সময়ে সিউডো-পোর্টেবল ত্রুটি বার্তা তৈরির উপায় হতে পারে।
ব্রাইস এম। ডেম্পসে

4
আমি মনে করি এই উত্তরটি কোডটির প্রেরণাকে খুব ভালভাবে ব্যাখ্যা করে তবে আমি যুক্ত করতে চাই যে (1) কিছু সংকলক sizeof(T)সংকলন ব্যর্থ না হয়ে অসম্পূর্ণ প্রকারের জন্য 0 এ মূল্যায়ন করেছে। এটি অবশ্য মেনে চলা আচরণ নয়। (২) যেহেতু সি ++ ১১, তাই ব্যবহার static_assert((sizeof(T) > 0), "T must be a complete type");করা একটি উচ্চতর (এবং আইডোমেটিক) সমাধান হতে পারে।
5gon12eder

@ 5gon12eder; দয়া করে একটি সি ++ সংকলকের একটি উদাহরণ সরবরাহ করুন যা " sizeof(T)অসম্পূর্ণ প্রকারের জন্য 0 থেকে মূল্যায়ন করুন" আছে।
চিয়ার্স এবং এইচটিএইচ - আল্ফ

4
আমি কখনও এই ধরনের সংকলক ব্যবহার করি নি এবং তারা এতক্ষণে মারা গেছে যে শুনে আমি অবাক হব না। এবং তাদের না থাকলেও, অ-মেনে চলার বাস্তবায়ন সম্পর্কে যত্ন না করা একটি বৈধ সিদ্ধান্ত। তবুও, libstdc ++ এবং libc ++ উভয়ই স্বতন্ত্রstatic_assert(sizeof(T) > 0, "…"); বাস্তবায়নে std::unique_ptrপ্রকারটি সম্পূর্ণ কিনা তা নিশ্চিত করতে ব্যবহার করে ...
5gon12eder

4
… সুতরাং আমি মনে করি এটি নিরাপদ বলে মূর্তিমান। যাইহোক, যেহেতু sizeof(T)একটি বুলিয়ান প্রসঙ্গে মূল্যায়ন করা ঠিকঠাক পরীক্ষার সমতুল্য sizeof(T) > 0, তাই সম্ভবত নান্দনিক কারণে ব্যতীত সত্যিকার অর্থে এটি গুরুত্বপূর্ণ নয়।
5gon12eder

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.