তুচ্ছ বস্তুর জন্য `this` এ স্থান নির্ধারণকে নতুন বলা নিরাপদ?


20

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

ধরা যাক আমার একটি তুচ্ছ শ্রেণি রয়েছে যার কোনও সংস্থার মালিকানা নেই এবং খালি ডেস্ট্রাক্টর এবং ডিফল্ট নির্মাণকারী রয়েছে। এটি শ্রেণীর সূচনা সহ কয়েকটি মুখ্য সদস্যের ভেরিয়েবল রয়েছে; তাদের মধ্যে একটিও নয় const

আমি deInitহাত দিয়ে পদ্ধতি না লিখে পুনরায় আরম্ভ এবং এই জাতীয় শ্রেণীর আপত্তি করতে চাই । এটি কি এইভাবে করা নিরাপদ?

void A::deInit()
{
  new (this)A{};
}

আমি এটি নিয়ে কোনও সমস্যা দেখতে পাচ্ছি না - বস্তু সর্বদা বৈধ অবস্থায় থাকে, thisএখনও একই ঠিকানার দিকে নির্দেশ করে; তবে এটি সি ++ তাই আমি নিশ্চিত হতে চাই।


2
অবজেক্ট কনস্টের কোনও সদস্য কি?
নাথান অলিভার

2
এটি বৈধ হলে এটি কি সমান হবে *this = A{};?
কেভিন

2
@ আমোম *this = A{};মানে, this->operator=(A{});অর্থাত্ একটি অস্থায়ী অবজেক্ট তৈরি করুন এবং এটিকে কার্যভার করুন , অস্থায়ী *thisমানগুলির সাথে সমস্ত ডেটা সদস্যের মানকে প্রতিস্থাপন করুন। যেহেতু আপনি যা চান তা (এবং আমার মতে) একটি নতুন স্থান নির্ধারণের চেয়ে বেশি পঠনযোগ্য, আমি পরিবর্তে সেই সাথে যাব।
কেভিন

1
@ কেহিন ওহ, আমার খারাপ, আপনি ঠিক বলেছেন। থান - আমার মনে হয় অনুলিপিটি যদি সমান হয়?
আমোম

1
ক্লাসটি কথায় ব্যাখ্যা করার পরিবর্তে পুরো ক্লাসটি লেখার চেয়ে আরও ভাল, কেবল একটি পদ্ধতি নয়। দেখতে sscce.org
BЈовић

উত্তর:


17

এর বৈধতা অনুসারে delete this, নতুন স্থাপনার thisঅনুমতি দেওয়া পর্যন্ত আমি জানি। এছাড়াও, thisবা অন্যান্য পূর্ব-বিদ্যমান পয়েন্টার / রেফারেন্সগুলি পরে ব্যবহার করা যেতে পারে সে সম্পর্কিত, কয়েকটি বিধিনিষেধ রয়েছে:

[Basic.life]

যদি কোনও অবজেক্টের জীবদ্দশায় শেষ হয়ে যাওয়ার পরে এবং যে স্টোরেজটি দখলকৃত বস্তুটি পুনরায় ব্যবহার বা মুক্তি দেওয়া হয় তার আগে, কোনও নতুন অবজেক্টটি স্টোরেজ অবস্থানে তৈরি করা হয় যা আসল বস্তুটি দখল করে, একটি পয়েন্টার যা মূল বস্তুকে নির্দেশ করে, একটি রেফারেন্স মূল অবজেক্টের সাথে উল্লেখ করা হয়, বা মূল অবজেক্টের নাম স্বয়ংক্রিয়ভাবে নতুন বস্তুর উল্লেখ করবে এবং একবার নতুন অবজেক্টটির জীবনকাল শুরু হয়ে গেলে নতুন অবজেক্টটি ম্যানিপুলেট করতে ব্যবহার করা যেতে পারে, যদি:

  • নতুন অবজেক্টের জন্য সঞ্চয়স্থান হ'ল স্টোরেজ অবস্থানটি ওভারলে করে যা মূল বস্তুটি দখল করে এবং
  • নতুন অবজেক্টটি মূল ধরণের (শীর্ষ স্তরের সিভি-কোয়ালিফায়ারকে উপেক্ষা করে) এবং একই ধরণের
  • মূল অবজেক্টের ধরণটি কনস্ট-কোয়ালিটিড নয়, এবং, যদি কোনও শ্রেণীর ধরণ থাকে তবে এমন কোনও অ স্থিতিশীল ডেটা সদস্য না থাকে যার প্রকারটি কনস্ট-কোয়ালিফাইড বা রেফারেন্স টাইপ, এবং
  • মূল অবজেক্ট বা নতুন বস্তুটিই কোনও সম্ভাব্য-ওভারল্যাপিং সাবোবজেক্ট নয় ([অন্তঃব্যবজেক্ট])।

প্রথম দুটি এই উদাহরণে সন্তুষ্ট, তবে শেষ দুটি বিবেচনায় নেওয়া দরকার।

তৃতীয় পয়েন্টটি সম্পর্কে, ফাংশনটি নন-কনস্টিটেড-কোয়ালিটিযুক্ত, এটি ধরে নেওয়া মোটামুটি নিরাপদ হওয়া উচিত যে আসল অবজেক্টটি অবিচ্ছিন্ন is যদি দৃ the়তা দূরে ফেলে দেওয়া হয় তবে দোষটি কলারের দিকে থাকে। কনস্ট / রেফারেন্স সদস্য সম্পর্কে, আমি মনে করি যে এটি নির্ধারিত বলে জোর করে পরীক্ষা করা যায়:

static_assert(std::is_trivial_v<A> && std::is_copy_assignable_v<A>);

অবশ্যই, যেহেতু অ্যাসিনেবিলিটি হ'ল একটি প্রয়োজনীয়তা, আপনি কেবল তার পরিবর্তে কেবল *this = {};একই প্রোগ্রামটি তৈরির প্রত্যাশা করতে পারেন। সম্ভবত আরও আকর্ষণীয় ব্যবহারের ক্ষেত্রে *thisঅন্য ধরণের কোনও অবজেক্টের স্মৃতি পুনঃব্যবহার করা হতে পারে (যা ব্যবহারের প্রয়োজনীয়তাগুলিকে ব্যর্থ করবে this, কমপক্ষে পুনরায় ব্যাখ্যা না করে)।

এর অনুরূপ delete this, নতুন thisস্থাপনাটি খুব সম্ভবতই "নিরাপদ" হিসাবে বর্ণিত হতে পারে।


মজাদার. এই ধরণের সমস্ত শর্তটি কোনও ধরণের বৈশিষ্ট্যে স্ট্যাটিক_সেসারে সন্তুষ্ট কিনা তা নিশ্চিত করা কি সম্ভব?
কনস্ট্যান্ডের

1
@ আমমম আমার মনে হয় না সাবোবজেক্ট হওয়া এমন কিছু যা পরীক্ষা করা যেতে পারে। কনস্ট বা রেফারেন্স সদস্যরা ক্লাসটি অ-নিয়োগযোগ্য করে তুলবে, যা আমি মনে করি না তুচ্ছ শ্রেণীর জন্য অন্যথায় ঘটতে পারে।
এরেরিকা

এর অর্থ কি এই দৃness়তা সম্পর্কে কঠোর আলিয়াজিং খেলাতে আসে? আপনি কি উদাহরণ দিতে পারেন যেখানে এটি কার্যকর হতে পারে?
darune

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

1
বিপরীত delete ptrহয় new T()। বিপরীত new(ptr)T{}হয় ptr->~T();stackoverflow.com/a/8918942/845092
গরুর হাঁসের

7

এগুলি অন্তর্ভুক্ত থাকা বিধিগুলি [বেসিক লাইফ] / 5 এ রয়েছে

কোনও প্রোগ্রাম স্টোরেজটি পুনরায় ব্যবহার করে যা অবজেক্টটি দখল করে তা পুনরায় ব্যবহার করে বা স্পষ্টভাবে শ্রেণীর ধরণের কোনও অবজেক্টের জন্য ডেস্ট্রাক্টরকে কল করে any শ্রেণীর ধরণের কোনও অবজেক্টের জন্য, প্রোগ্রামটি স্ট্রাকচারটি পুনঃব্যবহার করা বা মুক্তি দেওয়ার আগে স্পষ্টভাবে ডেস্ট্রাক্টরকে কল করতে হবে না; তবে, যদি ডেস্ট্রাক্টরের কাছে সুস্পষ্ট কল না পাওয়া যায় বা স্টোরেজ প্রকাশের জন্য মুছা-এক্সপ্রেশন ব্যবহার না করা হয়, তবে ডেস্ট্রাক্টরকে স্পষ্টতই বলা হয় না এবং যে কোনও প্রোগ্রাম যা ধ্বংসকারী দ্বারা উত্পাদিত পার্শ্ব প্রতিক্রিয়াগুলির উপর নির্ভর করে তার অপরিজ্ঞাত আচরণ রয়েছে behavior

এবং [বেসিক.লাইফ] / 8

যদি কোনও অবজেক্টের জীবদ্দশায় শেষ হয়ে যাওয়ার পরে এবং যে স্টোরেজটি দখলকৃত বস্তুটি পুনরায় ব্যবহার বা মুক্তি দেওয়া হয় তার আগে, কোনও নতুন অবজেক্টটি স্টোরেজ অবস্থানে তৈরি করা হয় যা আসল বস্তুটি দখল করে, একটি পয়েন্টার যা মূল বস্তুকে নির্দেশ করে, একটি রেফারেন্স মূল অবজেক্টের সাথে উল্লেখ করা হয়, বা মূল অবজেক্টের নাম স্বয়ংক্রিয়ভাবে নতুন বস্তুর উল্লেখ করবে এবং একবার নতুন অবজেক্টটির জীবনকাল শুরু হয়ে গেলে নতুন অবজেক্টটি ম্যানিপুলেট করতে ব্যবহার করা যেতে পারে, যদি:

  • নতুন অবজেক্টের জন্য সঞ্চয়স্থান হ'ল স্টোরেজ অবস্থানটি ওভারলে করে যা মূল বস্তুটি দখল করে এবং

  • নতুন অবজেক্টটি মূল ধরণের (শীর্ষ স্তরের সিভি-কোয়ালিফায়ারকে উপেক্ষা করে) এবং একই ধরণের

  • মূল অবজেক্টের ধরণটি কনস্ট-কোয়ালিটিড নয়, এবং, যদি কোনও শ্রেণীর ধরণ থাকে তবে এমন কোনও অ স্থিতিশীল ডেটা সদস্য না থাকে যার প্রকারটি কনস্ট-কোয়ালিফাইড বা রেফারেন্স টাইপ, এবং

  • মূল অবজেক্ট বা নতুন বস্তুটিই কোনও সম্ভাব্য-ওভারল্যাপিং সাবোবজেক্ট নয় ([অন্তঃব্যবজেক্ট])।

যেহেতু আপনার জিনিসটি তুচ্ছ, আপনি [বেসিক.লাইফ] / 5 সম্পর্কে চিন্তা করতে হবে না এবং যতক্ষণ আপনি [বেসিক.লাইফ] / 8 থেকে বুলেট পয়েন্টগুলি সন্তুষ্ট করেন, ততক্ষণ এটি নিরাপদ।

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