c++ উনল সি++ 11 রিটার্ন মান অপ্টিমাইজেশান বা সরানো?




সি++ বই (4)

যদি আপনি একটি স্থানীয় পরিবর্তনশীল ফিরে আসছেন, move() ব্যবহার করবেন না। এটি কম্পাইলারকে NRVO ব্যবহার করার অনুমতি দেবে এবং এটি ব্যর্থ হতে পারে, কম্পাইলারটিকে এখনও একটি পদক্ষেপ সম্পাদন করার অনুমতি দেওয়া হবে (স্থানীয় ভেরিয়েবলগুলি return স্টেটমেন্টের মধ্যে R- মানগুলি হয়ে যাবে)। যে প্রেক্ষিতে move() ব্যবহার করা সহজভাবে NRVOকে বাধা দেয় এবং কম্পাইলারটিকে একটি পদক্ষেপ ব্যবহার করতে বাধ্য করে (বা সরানো না হলে একটি অনুলিপি)। যদি আপনি স্থানীয় পরিবর্তনশীল ছাড়া অন্য কিছু ফেরত দিচ্ছেন তবে NRVO কোনও বিকল্প নয় এবং যদি আপনি (এবং শুধুমাত্র যদি) বস্তুটি move() তবে এটি move() ব্যবহার করা উচিত।

যখন আমি std::move ব্যবহার করবো তখন আমি বুঝতে পারছি না এবং যখন আমি কম্পাইলারকে অপ্টিমাইজ করতে দিই ... উদাহরণস্বরূপ:

using SerialBuffer = vector< unsigned char >;

// let compiler optimize it
SerialBuffer read( size_t size ) const
{
    SerialBuffer buffer( size );
    read( begin( buffer ), end( buffer ) );
    // Return Value Optimization
    return buffer;
}

// explicit move
SerialBuffer read( size_t size ) const
{
    SerialBuffer buffer( size );
    read( begin( buffer ), end( buffer ) );
    return move( buffer );
}

আমি যা ব্যবহার করা উচিত?


সমস্ত ফেরতের মানগুলি ইতিমধ্যেই moved বা অপ্টিমাইজ করা হয়েছে, সুতরাং ফেরত মানগুলির সাথে স্পষ্টভাবে সরানোর প্রয়োজন নেই।

কম্পাইলার স্বয়ংক্রিয়ভাবে ফেরতের মান (কপিটি অপ্টিমাইজ করার জন্য) সরানোর অনুমতি দেয় এবং এমনকি পদক্ষেপটি অপটিমাইজ করে!

N3337 স্ট্যান্ডার্ড খসড়া (সি ++ 11) বিভাগ 12.8 :

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

[...]

উদাহরণ :

class Thing {
public:
Thing();
   ~Thing();
   Thing(const Thing&);
};

Thing f() {
   Thing t;
   return t;
}

Thing t2 = f();

এখানে ক্লাসের Thing অনুলিপি কনস্ট্রাক্টরকে দুটি কল বাদ দেওয়ার জন্য এলিয়েন্সের মানদণ্ড সংযুক্ত করা যেতে পারে: ফাংশন f() ফিরতি মূল্যের জন্য স্থানীয় অটোমেটিক বস্তু t অস্থায়ী বস্তুর অনুলিপি করা এবং অস্থায়ী বস্তুর অনুলিপি t2 । কার্যকরীভাবে, স্থানীয় বস্তুটির t2 সরাসরি বিশ্বব্যাপী বস্তুটি টি 2 সূচনা হিসাবে দেখা যেতে পারে এবং প্রোগ্রামটির প্রস্থান এ বস্তুর ধ্বংস ঘটবে। Thing একটি সরানো কনস্ট্রাক্টারের একই প্রভাব রয়েছে, তবে এটি অস্থায়ী বস্তুর থেকে t2 যা সরানো হয় তা সরানো হয়। - শেষ উদাহরণ ]

যখন একটি কপি অপারেশন elision জন্য মানদণ্ড পূরণ করা হয় বা পূরণ করা হবে যে উত্স বস্তু একটি ফাংশন পরামিতি, এবং কপি করা বস্তু একটি lvalue দ্বারা নির্ধারিত হয়, কপি জন্য কন্সট্রাকটর নির্বাচন করতে ওভারলোড রেজল্যুশন, প্রথম বস্তুর একটি rvalue দ্বারা মনোনীত হয় হিসাবে সঞ্চালিত। যদি ওভারলোড রেজোলিউশন ব্যর্থ হয় বা নির্বাচিত কনস্ট্রাক্টারের প্রথম প্যারামিটারের ধরনটি বস্তুর ধরন (সম্ভবত সিভি-যোগ্যতা) এর একটি রেভেলিউ রেফারেন্স না থাকে তবে ওভারলোড রেজোলিউশনটি আবার সঞ্চালিত হয়, বস্তুকে তরল হিসাবে বিবেচনা করা হয়।


এটা বেশ সহজ।

return buffer;

যদি আপনি এটি করেন, তাহলে হয় NRVO হয় বা এটি হবে না। যদি এটি না ঘটে তবে buffer থেকে সরানো হবে।

return std::move( buffer );

যদি আপনি এটি করেন, তবে NVRO ঘটবে না , এবং buffer থেকে সরানো হবে।

সুতরাং std::move এখানে std::move ব্যবহার করে লাভের কিছু নেই, এবং অনেক হারান।

এই নিয়মের একটি পার্থক্য রয়েছে:

Buffer read(Buffer&& buffer) {
    //...
    return std::move( buffer );
}

যদি buffer একটি রেভালিউ রেফারেন্স হয়, তবে আপনাকে std::move ব্যবহার করতে হবে। কারণ রেফারেন্সগুলি এনআরভিওর জন্য যোগ্য নয়, তাই std::move ছাড়া এটি একটি অনুলিপি থেকে একটি অনুলিপি হতে পারে।

এই নিয়মটির একটি উদাহরণ মাত্র "সর্বদা রেভালু রেফারেন্সগুলি এবং forward সার্বজনীন রেফারেন্সগুলি move ", যা এই নিয়মটিকে অগ্রাধিকার দেয় যে "কখনও ফেরত মান move না"।


একচেটিয়াভাবে প্রথম পদ্ধতি ব্যবহার করুন:

Foo f()
{
  Foo result;
  mangle(result);
  return result;
}

যদি এটি উপলব্ধ থাকে তবে এটি ইতিমধ্যে পদক্ষেপ গঠনকারীর ব্যবহারের অনুমতি দেবে। প্রকৃতপক্ষে, কপি Elision অনুমোদিত যখন একটি স্থানীয় পরিবর্তনশীল একটি return বিবৃতিতে একটি rvalue রেফারেন্স আবদ্ধ করতে return

আপনার দ্বিতীয় সংস্করণ সক্রিয়ভাবে কপি elision নিষিদ্ধ। প্রথম সংস্করণ সর্বজনীনভাবে ভাল।







rvo