কপি এলিজেন এবং রিটার্ন মান অপ্টিমাইজেশন কী কী?


377

অনুলিপি কি? (নাম দেওয়া) রিটার্ন মান অপ্টিমাইজেশন কী? তারা কি বোঝায়?

তারা কোন পরিস্থিতিতে ঘটতে পারে? সীমাবদ্ধতা কি?


1
কপির এলিজেন্স এটি দেখার এক উপায়; অবজেক্ট এলিজেন বা অবজেক্ট ফিউশন (বা বিভ্রান্তি) হ'ল অন্য মত।
কৌতূহলী

আমি এই লিঙ্কটি সহায়ক বলে মনে করেছি।
সূক্ষ্মদর্শক

উত্তর:


246

ভূমিকা

প্রযুক্তিগত ওভারভিউয়ের জন্য - এই উত্তরটি এড়িয়ে যান

সাধারণ ক্ষেত্রে যেখানে অনুলিপি এলিজেন ঘটে - এই উত্তরটি এড়িয়ে যান

কিছু পরিস্থিতিতে অতিরিক্ত (সম্ভাব্য ব্যয়বহুল) অনুলিপি প্রতিরোধ করতে বেশিরভাগ সংকলক দ্বারা কপি এলিজেন বাস্তবায়ন একটি অপ্টিমাইজেশন। এটি মান দ্বারা প্রত্যাবর্তন করে বা বাস্তবে পাস-বাই-মানকে সম্ভব করে তোলে (সীমাবদ্ধতা প্রযোজ্য)।

এটি অপ্টিমাইজেশনের একমাত্র ফর্ম যা এলিডগুলি (হ্যাক!) বিস্ময়কর নিয়ম - অনুলিপি / মুভিংয়ের পার্শ্ব-প্রতিক্রিয়া থাকলেও অনুলিপি প্রয়োগ করা যেতে পারে

নিম্নলিখিত উদাহরণটি উইকিপিডিয়া থেকে নেওয়া :

struct C {
  C() {}
  C(const C&) { std::cout << "A copy was made.\n"; }
};

C f() {
  return C();
}

int main() {
  std::cout << "Hello World!\n";
  C obj = f();
}

সংকলক এবং সেটিংসের উপর নির্ভর করে, নিম্নলিখিত আউটপুটগুলি সমস্ত বৈধ :

ওহে বিশ্ব!
একটি কপি তৈরি করা হয়েছিল।
একটি কপি তৈরি করা হয়েছিল।


ওহে বিশ্ব!
একটি কপি তৈরি করা হয়েছিল।


ওহে বিশ্ব!

এর অর্থ হ'ল কম বস্তু তৈরি করা যায়, সুতরাং আপনি ডেকে পাঠানো নির্দিষ্ট সংখ্যক ধ্বংসকারীদের উপরও নির্ভর করতে পারবেন না। অনুলিপি / মুভ-কনস্ট্রাক্টর বা ডেস্ট্রাক্টরগুলির ভিতরে আপনার কাছে সমালোচনা যুক্তিযুক্ত হওয়া উচিত নয়, কারণ আপনি তাদের ডেকে যাওয়ার উপর নির্ভর করতে পারবেন না।

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

সি ++ ১ :: সি ++ ১ of অনুসারে, কোনও বস্তু সরাসরি ফেরত দেওয়া হলে অনুলিপি নিশ্চিত করা হবে:

struct C {
  C() {}
  C(const C&) { std::cout << "A copy was made.\n"; }
};

C f() {
  return C(); //Definitely performs copy elision
}
C g() {
    C c;
    return c; //Maybe performs copy elision
}

int main() {
  std::cout << "Hello World!\n";
  C obj = f(); //Copy constructor isn't called
}

2
আপনি কি ব্যাখ্যা করতে পারবেন 2 য় আউটপুট কখন হয় এবং 3 য় কখন হয়?
ঝাংক্সাওচেন

3
কখন এবং কীভাবে সংকলক সেই উপায়ে অপ্টিমাইজ করার সিদ্ধান্ত নেয় @ জাঙ্গক্সাওচেন।
লুচিয়ান গ্রিগোর

10
@ ঝাংক্সাওচেন, প্রথম আউটপুট: অনুলিপি 1 কোনও টেম্পে ফিরে আসার থেকে, এবং টেম্প থেকে 2 টি অনুলিপি করার জন্য; ২ য়টি হল যখন উপরের কোনওটি অপ্টিমাইজ করা হয়, সম্ভবত পুনরায় সংযুক্তি অনুলিপিটি আলাদা করা হয়; এই উভয় পক্ষই সম্মতিযুক্ত
বিজয়ী

2
হুম, তবে আমার মতে, এটি নির্ভর করে এমন একটি বৈশিষ্ট্য যা আমরা নির্ভর করতে পারি। কারণ আমরা যদি এটি না করতে পারি তবে এটি আধুনিক সি ++ (আরভিও বনাম এসটিডি :: পদক্ষেপে) আমাদের ফাংশনগুলি কার্যকর করার পথে মারাত্মকভাবে প্রভাব ফেলবে। সিপিসন 2014 ভিডিওর কিছু দেখার সময়, আমি সত্যিই ধারণা পেয়েছিলাম যে সমস্ত আধুনিক সংকলক সর্বদা আরভিও করেন। তদুপরি, আমি কোথাও পড়েছি যা কোনও অপ্টিমাইজেশন ছাড়াই, সংকলকরা এটি প্রয়োগ করে। তবে অবশ্যই আমি এটি সম্পর্কে নিশ্চিত নই। এজন্যই আমি জিজ্ঞাসা করছি।
j00hi

8
@ j00hi: রিটার্নের বিবৃতিতে কখনই মুভটি লিখবেন না - আরভিও প্রয়োগ না করা থাকলে, ফেরতের মান যাই হোক না কেন ডিফল্টরূপে সরানো হয়।
মাইক এমবি 10:38

96

স্ট্যান্ডার্ড রেফারেন্স

কম প্রযুক্তিগত দর্শন ও প্রবর্তনের জন্য - এই উত্তরটি এড়িয়ে যান

সাধারণ ক্ষেত্রে যেখানে অনুলিপি এলিজেন ঘটে - এই উত্তরটি এড়িয়ে যান

অনুলিপি বর্ধিতকরণটি মানটিতে সংজ্ঞায়িত করা হয়:

12.8 শ্রেণি অবজেক্টগুলি অনুলিপি করা এবং সরিয়ে নেওয়া

যেমন

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

- ক্লাস রিটার্ন টাইপের সাথে ফাংশনে একটি রিটার্ন বিবৃতিতে যখন অভিব্যক্তিটি ফাংশন রিটার্ন টাইপের মতো একই সিভানক্যালিফায়েড টাইপের সাথে অ-উদ্বায়ী স্বয়ংক্রিয় বস্তুর (কোনও ফাংশন বা ক্যাচ-ক্লজ প্যারামিটার বাদে) নাম হয়, ফাংশনটির রিটার্ন ভ্যালুতে সরাসরি স্বয়ংক্রিয় অবজেক্টটি তৈরি করে অনুলিপি / মুভ অপারেশন বাদ দেওয়া যেতে পারে

- একটি থ্রো-এক্সপ্রেশন-এ, যখন অপারেন্ডটি একটি অ-উদ্বায়ী স্বয়ংক্রিয় বস্তুর নাম (কোনও ফাংশন বা ক্যাচ-ক্লজ প্যারামিটার বাদে) যার স্কোপটি অভ্যন্তরীণ ঘেরের চেষ্টা-ব্লকের শেষের বাইরে প্রসারিত হয় না (যদি সেখানে থাকে) এক), অপারেশন থেকে ব্যতিক্রম অবজেক্টের (15.1) অনুলিপি / মুভিং অপারেশনটি স্বয়ংক্রিয় অবজেক্টটি সরাসরি ব্যতিক্রম বস্তুতে তৈরি করে বাদ দেওয়া যেতে পারে can

- যখন কোনও অস্থায়ী শ্রেণীর অবজেক্ট যা রেফারেন্সের সাথে আবদ্ধ হয়নি (12.2) একই সিভি-অযোগ্যতাযুক্ত শ্রেণীর সাথে কোনও শ্রেণি অবজেক্টে অনুলিপি / স্থানান্তরিত হবে, তখন অনুলিপি / মুভ ক্রিয়াকলাপটি অস্থায়ী বস্তুটি সরাসরি তৈরি করে বাদ দেওয়া যেতে পারে বাদ দেওয়া অনুলিপি / সরানোর লক্ষ্য

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

123) যেহেতু দু'টির পরিবর্তে কেবলমাত্র একটি অবজেক্ট ধ্বংস হয়ে যায় এবং একটি অনুলিপি / মুভ কনস্ট্রাক্টর কার্যকর হয় না, এখনও প্রতি নির্মিত প্রতিটিটির জন্য একটি অবজেক্ট ধ্বংস রয়েছে।

প্রদত্ত উদাহরণটি হ'ল:

class Thing {
public:
  Thing();
  ~Thing();
  Thing(const Thing&);
};
Thing f() {
  Thing t;
  return t;
}
Thing t2 = f();

এবং ব্যাখ্যা:

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


1
এটি কি সি ++ 17 স্ট্যান্ডার্ড থেকে বা পূর্ববর্তী সংস্করণ থেকে?
নিলস

90

অনুলিপি সাধারণ ফর্ম

প্রযুক্তিগত ওভারভিউয়ের জন্য - এই উত্তরটি এড়িয়ে যান

কম প্রযুক্তিগত দর্শন ও প্রবর্তনের জন্য - এই উত্তরটি এড়িয়ে যান

(নামযুক্ত) রিটার্ন মান অপ্টিমাইজেশন কপি এলিজেনের একটি সাধারণ ফর্ম। এটি এমন পরিস্থিতিতে নির্দেশ করে যেখানে কোনও পদ্ধতি থেকে মান দ্বারা প্রত্যাবর্তিত কোনও অবজেক্টের অনুলিপি থাকে। স্ট্যান্ডার্ডে বর্ণিত উদাহরণটি নামটির প্রত্যাবর্তন মান অপ্টিমাইজেশান চিত্রিত করে , যেহেতু বস্তুর নাম দেওয়া হয়েছে।

class Thing {
public:
  Thing();
  ~Thing();
  Thing(const Thing&);
};
Thing f() {
  Thing t;
  return t;
}
Thing t2 = f();

যখন কোনও অস্থায়ী ফিরে আসে নিয়মিত রিটার্ন মান অপ্টিমাইজেশন ঘটে:

class Thing {
public:
  Thing();
  ~Thing();
  Thing(const Thing&);
};
Thing f() {
  return Thing();
}
Thing t2 = f();

অন্যান্য সাধারণ জায়গাগুলি যেখানে কপির এলিজেন হয় সেগুলি হ'ল যখন অস্থায়ী মান দ্বারা পাস করা হয় :

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

foo(Thing());

বা যখন একটি ব্যতিক্রম নিক্ষেপ করা হয় এবং মান দ্বারা ধরা হয় :

struct Thing{
  Thing();
  Thing(const Thing&);
};

void foo() {
  Thing c;
  throw c;
}

int main() {
  try {
    foo();
  }
  catch(Thing c) {  
  }             
}

অনুলিপি সাধারণের সীমাবদ্ধতাগুলি হ'ল:

  • একাধিক রিটার্ন পয়েন্ট
  • শর্তসাপেক্ষ সূচনা

বেশিরভাগ বাণিজ্যিক-গ্রেড সংকলক কপির এলিজেন এবং (এন) আরভিও সমর্থন করে (অপ্টিমাইজেশন সেটিংসের উপর নির্ভর করে)।


4
আমি "সাধারণ সীমাবদ্ধতা" বুলেট পয়েন্টগুলি দেখতে একটু আগ্রহী হতে আগ্রহী ... কী কারণে এই সীমিত কারণগুলি তৈরি হয়?
ফোনেটেগার

@ ফোনেট্যাগারটি আমি এমএসডিএন নিবন্ধের সাথে লিঙ্ক করেছি, আশা করি কিছু জিনিস সাফ হয়ে যায়।
লুচিয়ান গ্রিগোর

54

অনুলিপি এলিজার একটি সংকলক অপ্টিমাইজেশন কৌশল যা অপ্রয়োজনীয় অনুলিপি / অবজেক্টগুলিকে সরিয়ে দেয়।

নিম্নলিখিত পরিস্থিতিতে, একটি সংকলককে অনুলিপি / সরানো ক্রিয়াকলাপ বাদ দেওয়ার অনুমতি দেওয়া হয় এবং সেইজন্য সংশ্লিষ্ট নির্মাণকারীকে কল করতে না:

  1. এনআরভিও (নামযুক্ত রিটার্ন মান অপ্টিমাইজেশন) : যদি কোনও ফাংশন মান অনুসারে শ্রেণীর প্রকারটি দেয় এবং রিটার্ন স্টেটমেন্টের অভিব্যক্তি স্বয়ংক্রিয় স্টোরেজ সময়কাল (যা কোনও ফাংশন প্যারামিটার নয়) সহ একটি অ-উদ্বায়ী বস্তুর নাম হয়, তবে অনুলিপি / সরানো এটি একটি অপ-অপ্টিমাইজ করা সংকলক বাদ দেওয়া যেতে পারে performed যদি তা হয় তবে ফিরে আসা মানটি স্টোরেজটিতে সরাসরি তৈরি করা হয় যেখানে ফাংশনের ফেরতের মান অন্যথায় স্থানান্তরিত বা অনুলিপি করা হবে।
  2. আরভিও (রিটার্ন ভ্যালু অপ্টিমাইজেশন) : যদি ফাংশনটি কোনও নামহীন অস্থায়ী বস্তুটি ফিরিয়ে দেয় বা কোনও নিষ্পাপ সংকলক দ্বারা গন্তব্যে অনুলিপি করা হয়, তবে অনুলিপি বা সরানো 1 অনুযায়ী বাদ দেওয়া যাবে।
#include <iostream>  
using namespace std;

class ABC  
{  
public:   
    const char *a;  
    ABC()  
     { cout<<"Constructor"<<endl; }  
    ABC(const char *ptr)  
     { cout<<"Constructor"<<endl; }  
    ABC(ABC  &obj)  
     { cout<<"copy constructor"<<endl;}  
    ABC(ABC&& obj)  
    { cout<<"Move constructor"<<endl; }  
    ~ABC()  
    { cout<<"Destructor"<<endl; }  
};

ABC fun123()  
{ ABC obj; return obj; }  

ABC xyz123()  
{  return ABC(); }  

int main()  
{  
    ABC abc;  
    ABC obj1(fun123());//NRVO  
    ABC obj2(xyz123());//NRVO  
    ABC xyz = "Stack Overflow";//RVO  
    return 0;  
}

**Output without -fno-elide-constructors**  
root@ajay-PC:/home/ajay/c++# ./a.out   
Constructor    
Constructor  
Constructor  
Constructor  
Destructor  
Destructor  
Destructor  
Destructor  

**Output with -fno-elide-constructors**  
root@ajay-PC:/home/ajay/c++# g++ -std=c++11 copy_elision.cpp -fno-elide-constructors    
root@ajay-PC:/home/ajay/c++# ./a.out   
Constructor  
Constructor  
Move constructor  
Destructor  
Move constructor  
Destructor  
Constructor  
Move constructor  
Destructor  
Move constructor  
Destructor  
Constructor  
Move constructor  
Destructor  
Destructor  
Destructor  
Destructor  
Destructor  

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

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

#include <iostream>     
int n = 0;    
class ABC     
{  public:  
 ABC(int) {}    
 ABC(const ABC& a) { ++n; } // the copy constructor has a visible side effect    
};                     // it modifies an object with static storage duration    

int main()   
{  
  ABC c1(21); // direct-initialization, calls C::C(42)  
  ABC c2 = ABC(21); // copy-initialization, calls C::C( C(42) )  

  std::cout << n << std::endl; // prints 0 if the copy was elided, 1 otherwise
  return 0;  
}

Output without -fno-elide-constructors  
root@ajay-PC:/home/ayadav# g++ -std=c++11 copy_elision.cpp  
root@ajay-PC:/home/ayadav# ./a.out   
0

Output with -fno-elide-constructors  
root@ajay-PC:/home/ayadav# g++ -std=c++11 copy_elision.cpp -fno-elide-constructors  
root@ajay-PC:/home/ayadav# ./a.out   
1

জিসিসি -fno-elide-constructorsঅনুলিপি অনুলিপি করার বিকল্প সরবরাহ করে । যদি আপনি সম্ভাব্য অনুলিপি এলিজেন এড়াতে চান তবে ব্যবহার করুন -fno-elide-constructors

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

উপসংহার

প্রতিটি অনুলিপি এলিজের সাথে, অনুলিপিটির একটি নির্মাণ এবং একের সাথে মিলে যায় ধ্বংসকে বাদ দেওয়া হয়, সুতরাং সিপিইউর সময় সাশ্রয় হয় এবং একটি অবজেক্ট তৈরি হয় না, এইভাবে স্ট্যাক ফ্রেমে স্থান সাশ্রয় করে।


6
বিবৃতি ABC obj2(xyz123());এটি এনআরভিও বা আরভিও? এটি কি অস্থায়ী ভেরিয়েবল / অবজেক্টের মতো হচ্ছে না ABC xyz = "Stack Overflow";//RVO
আসিফ মোশতাক

3
আরভিওর আরও দৃ concrete় চিত্রণ পেতে, আপনি সংঘটিত করতে পারেন যে সংকলকটি উত্পন্ন করে (পৃথক দেখতে সংকলক পতাকা -fno-elide-builders পরিবর্তন করুন)। Godbolt.org/g/Y2KcdH
গ্যাব 好人 好人
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.