গ্যারান্টিযুক্ত অনুলিপি এলিজেন কীভাবে কাজ করে?


90

২০১ O সালের ওলু আইএসও সি ++ স্ট্যান্ডার্ডস সভায়, সরলিকৃত মান বিভাগগুলির মাধ্যমে গ্যারান্টেড কপি এলিজেন নামে একটি প্রস্তাবকে মান কমিটি কর্তৃক সি ++ 17 এ ভোট দেওয়া হয়েছিল।

গ্যারান্টেড কপি এলিজেন ঠিক কীভাবে কাজ করে? এটি কি এমন কিছু ক্ষেত্রে কভার করে যেখানে কপির এলিজেনের ইতিমধ্যে অনুমতি দেওয়া হয়েছিল, বা অনুলিপি এলিজির গ্যারান্টি রাখতে কোড পরিবর্তনগুলি দরকার?

উত্তর:


130

অনুলিপি এলিজেন বিভিন্ন পরিস্থিতিতে ঘটতে অনুমতি দেওয়া হয়েছিল। যাইহোক, এটি অনুমোদিত হলেও, কোডটি এখনও কাজ করতে সক্ষম হয়েছিল যেন অনুলিপিটি অনুপযুক্ত ছিল না। যথা, সেখানে একটি অ্যাক্সেসযোগ্য অনুলিপি এবং / অথবা মুভ কনস্ট্রাক্টর থাকতে হয়েছিল।

গ্যারান্টিযুক্ত কপি বিলোপ সি ++ ধারণা, এই ধরনের যে কিছু বিশেষ পরিস্থিতির যেখানে কপি / প্যাচসমূহ লুপ্ত হতে পারে আসলে একটি কপি / পদক্ষেপ ঘটান না একটি নম্বর redefines এ সব । সংকলক একটি অনুলিপি গোপন করছে না; মানটি বলে যে এরকম কোনও অনুলিপি কখনও ঘটতে পারে নি।

এই ফাংশনটি বিবেচনা করুন:

T Func() {return T();}

অন-গ্যারান্টিযুক্ত অনুলিপি এলিজেন নিয়মের অধীনে, এটি একটি অস্থায়ী তৈরি করবে, তারপরে সেই অস্থায়ী থেকে ফাংশনের রিটার্ন মানটিতে চলে যাবে। এই মুভ অপারেশনটি এলিডযুক্ত হতে পারে Tতবে এটি কখনও ব্যবহার না করা সত্ত্বেও একটি অ্যাক্সেসযোগ্য মুভ কনস্ট্রাক্টর থাকতে হবে।

একইভাবে:

T t = Func();

এটি হ'ল অনুলিপি t। এটির tরিটার্ন মান সহ আরম্ভের অনুলিপি করা হবে Func। যাইহোক, Tএখনও একটি মুভি কনস্ট্রাক্টর থাকতে হবে, যদিও এটি বলা হবে না।

গ্যারান্টিযুক্ত অনুলিপি এলিজিয়াল একটি মূল মূল্য প্রকাশের অর্থ পুনরায় সংজ্ঞা দেয় । প্রাক-সি ++ 17, মূল্যগুলি অস্থায়ী বস্তু। সি ++ ১ In-এ, একটি প্রাথমিক ধারণাটি কেবল এমন কিছু যা সাময়িকভাবে রূপায়িত করতে পারে তবে এটি এখনও অস্থায়ী নয়।

আপনি যদি প্রলিউয়ের ধরণের কোনও অবজেক্টটি আরম্ভ করার জন্য কোনও মূল্য ব্যবহার করেন, তবে কোনও অস্থায়ী বস্তুগত হয় না। আপনি যখন করেন return T();, এটি কোনও পূর্বমূল্যের মাধ্যমে ফাংশনের রিটার্ন মানকে আরম্ভ করে। যেহেতু ফাংশনটি ফিরে আসে T, তাই কোনও অস্থায়ী তৈরি হয় না; মূল্যের সূচনাটি প্রত্যক্ষভাবে প্রত্যক্ষ মানের সূচনা করে।

বোঝার বিষয়টি হ'ল, যেহেতু রিটার্ন মান একটি পূর্বমূল্য, এটি এখনও কোনও বস্তু নয় । এটি কেবল কোনও জিনিসের জন্য কেবল একটি সূচনাযাত্রা T()

আপনি যখন করেন T t = Func();, প্রত্যাবর্তনের মূল্যের মূল্য সরাসরি অবজেক্টটিকে আরম্ভ করে t; কোনও "অস্থায়ী এবং অনুলিপি / সরানো" পর্যায়ে নেই। যেহেতু Func()এর রিটার্ন মান হ'ল একটি মূল্যমানের সমতুল্য T(), tসরাসরি দ্বারা শুরু করা হয় T()ঠিক যেমনটি আপনি করেছেন T t = T()

যদি কোনও মূল্য অন্য কোনও উপায়ে ব্যবহার করা হয়, তবে মূল্যটি একটি অস্থায়ী বস্তুকে রূপায়িত করবে, যা সেই অভিব্যক্তিতে ব্যবহৃত হবে (বা কোনও অভিব্যক্তি না থাকলে ফেলে দেওয়া হবে)। সুতরাং আপনি যদি তা করেন const T &rt = Func();, তবে প্রাথমিক অস্থায়ী আজীবন এক্সটেনশনের স্টাফ সহ T(), যার উল্লেখটি অস্থায়ী (আরম্ভকারী হিসাবে ব্যবহার করে ) কার্যকর করা হবে rt

গ্যারান্টিযুক্ত এলিজেন্স আপনাকে অনুমতি দেয় এমন একটি জিনিস হ'ল অচল জিনিস যা ফেরত দেওয়া হয়। উদাহরণস্বরূপ, lock_guardঅনুলিপি করা বা সরানো যায় না, সুতরাং আপনার কোনও ফাংশন থাকতে পারে না যা এটি মূল্য দিয়ে ফিরিয়ে দেয়। তবে গ্যারান্টিযুক্ত অনুলিপি সহ, আপনি পারেন।

গ্যারান্টেড এলিজেন্স সরাসরি সূচনাতেও কাজ করে:

new T(FactoryFunction());

যদি মান অনুসারে FactoryFunctionরিটার্ন দেয় তবে Tএই অভিব্যক্তিটি বরাদ্দ মেমরিতে রিটার্নের মানটি অনুলিপি করবে না। এটি পরিবর্তে মেমরি বরাদ্দ করবে এবং বরাদ্দ মেমরিটি সরাসরি ফাংশন কলের জন্য রিটার্ন মান মেমরি হিসাবে ব্যবহার করবে

সুতরাং ফ্যাক্টরি ফাংশনগুলি যা মান অনুসারে প্রত্যাবর্তন করে সেগুলি এমনকি অজানা মেমরির সম্পর্কে সরাসরি না জেনে শুরু করতে পারে। এতক্ষণ এই ফাংশনগুলি অভ্যন্তরীণভাবে অবশ্যই গ্যারান্টিযুক্ত অনুলিপি নিয়মের অনুসরণ করে follow তাদের টাইপের একটি মূল্য ফেরত দিতে হবে T

অবশ্যই এটি কাজ করে:

new auto(FactoryFunction());

আপনি টাইপনেম লিখতে পছন্দ করেন না ক্ষেত্রে।


এটি সনাক্ত করা গুরুত্বপূর্ণ যে উপরের গ্যারান্টিগুলি কেবল মূল্যগুলির জন্য কাজ করে। এটি হল, নামযুক্ত ভেরিয়েবলটি ফেরত দেওয়ার সময় আপনি কোনও গ্যারান্টি পাবেন না :

T Func()
{
   T t = ...;
   ...
   return t;
}

এই উদাহরণস্বরূপ, tএখনও একটি অ্যাক্সেসযোগ্য অনুলিপি / সরানো কনস্ট্রাক্টর থাকতে হবে। হ্যাঁ, সংকলক অনুলিপি / সরানো অপ্টিমাইজ করতে বেছে নিতে পারেন। তবে সংকলকটিকে এখনও একটি অ্যাক্সেসযোগ্য অনুলিপি / সরানো কনস্ট্রাক্টরের অস্তিত্ব যাচাই করতে হবে।

সুতরাং নামমাত্র রিটার্ন মান অপ্টিমাইজেশনের (এনআরভিও) কোনও পরিবর্তন হয় না।


4
@ বেনভয়েগ্ট: অ-তুচ্ছ-অনুলিপি-অনুলিপিযোগ্য ব্যবহারকারী-সংজ্ঞায়িত প্রকারগুলিকে রেজিস্টারে স্থাপন করা এবিআই যে কার্যকর করতে পারে তা নয়, এলিজেন পাওয়া যায় কি না।
নিকল বোলাস

4
এখন যেহেতু বিধিগুলি সর্বজনীন, এটি "পূর্ববর্তিগুলি ইনিশিয়ালাইজেশন" ধারণাটি সহ আপডেট করা ভাল।
জোহানেস স্কাউব -

7
@ জোহানেস শ্যাব-লিটব: আপনি যদি সি ++ স্ট্যান্ডার্ডের মিনটিয়া সম্পর্কে সম্পূর্ণরূপে বেশি জানেন তবে এটি কেবল "দ্ব্যর্থক"। C ++ সম্প্রদায়ের 99% অংশের জন্য, আমরা জানি "গ্যারান্টিযুক্ত অনুলিপি" কী বোঝায়। বৈশিষ্ট্যটির প্রস্তাব দেওয়ার প্রকৃত কাগজটি এমনকি "গ্যারান্টিযুক্ত অনুলিপি" শিরোনামে রয়েছে । "সরলিকৃত মান বিভাগগুলির মাধ্যমে" কেবল যুক্ত করা বিভ্রান্তিকর এবং ব্যবহারকারীদের বুঝতে অসুবিধাজনক করে তুলেছে। এছাড়াও এটি একটি মিসনোমোর, যেহেতু এই বিধিগুলি মান বিভাগের কাছাকাছি নিয়মগুলিকে "সরল" করে না। আপনার পছন্দ হোক বা না হোক, "গ্যারান্টেড কপির এলিজেন" শব্দটি এই বৈশিষ্ট্যটিকে বোঝায় এবং অন্য কিছুই নয়।
নিকল বোলাস

4
আমি তাই একটি সিদ্ধান্ত নিতে এবং প্রায় এটি বহন করতে সক্ষম হতে চাই আমি অনুমান করি যে এটি std::function<T()>সত্যই একটি (এক শট) ।
ইয়াক্ক - অ্যাডাম নেভ্রামুমন্ট

4
@ লুকাসালিচ: এটি একটি সি ++ 11 প্রশ্ন। এই উত্তরটি একটি সি ++ 17 বৈশিষ্ট্য সম্পর্কে।
নিকল বোলাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.