কপির কন্সট্রাক্টরগুলি কখন ব্যবহার করতে হবে?


87

আমি জানি যে সি ++ সংকলক একটি শ্রেণীর জন্য একটি অনুলিপি নির্মাণকারী তৈরি করে। কোন ক্ষেত্রে আমাদের কোনও ব্যবহারকারী-সংজ্ঞায়িত অনুলিপি নির্মাণকারী লিখতে হবে? আপনি কিছু উদাহরণ দিতে পারেন?



4
আপনার নিজের অনুলিপি-কর্টরটি লেখার ক্ষেত্রে একটি: যখন আপনাকে গভীর অনুলিপিটি করতে হয়। আরও মনে রাখবেন যে আপনি কোনও সিটি তৈরি করার সাথে সাথেই আপনার জন্য কোনও ডিফল্ট কর্টর তৈরি করা হয়নি (যদি না আপনি ডিফল্ট কীওয়ার্ড ব্যবহার করেন)।
কঠোরচাওলা

উত্তর:


75

সংকলক দ্বারা উত্পাদিত অনুলিপি নির্ধারক সদস্য ভিত্তিক অনুলিপি করেন। কখনও কখনও এটি পর্যাপ্ত হয় না। উদাহরণ স্বরূপ:

class Class {
public:
    Class( const char* str );
    ~Class();
private:
    char* stored;
};

Class::Class( const char* str )
{
    stored = new char[srtlen( str ) + 1 ];
    strcpy( stored, str );
}

Class::~Class()
{
    delete[] stored;
}

storedএক্ষেত্রে সদস্য অনুসারে সদস্যের অনুলিপিটি বাফারের সদৃশ হবে না (কেবলমাত্র পয়েন্টারটি অনুলিপি করা হবে), তাই প্রথমে নষ্ট হওয়া বাফার ভাগ করে নেওয়ার সাথে বাফারটি delete[]সফলভাবে কল করবে এবং দ্বিতীয়টি অনির্ধারিত আচরণে চলে যাবে। আপনার গভীর অনুলিপি অনুলিপি নির্মাণকারীর প্রয়োজন (এবং পাশাপাশি অ্যাসাইনমেন্ট অপারেটর)।

Class::Class( const Class& another )
{
    stored = new char[strlen(another.stored) + 1];
    strcpy( stored, another.stored );
}

void Class::operator = ( const Class& another )
{
    char* temp = new char[strlen(another.stored) + 1];
    strcpy( temp, another.stored);
    delete[] stored;
    stored = temp;
}

10
এটি বিট-ওয়াইজ সম্পাদন করে না, তবে সদস্য-ভিত্তিক অনুলিপি যা শ্রেণিবদ্ধ সদস্যদের জন্য অনুলিপিটি-অনুলিপি করে।
জর্জি ফ্রিজচে

7
Assingment অপারেটরটি এর মতো লিখবেন না। এটি ব্যতিক্রম নিরাপদ নয়। (যদি নতুন একটি ব্যতিক্রম ছুঁড়ে ফেলে তবে অবজেক্টটি অপরিজ্ঞাত স্থানে মেমরির একটি বিচ্ছিন্ন অংশের দিকে নির্দেশ করে স্টোরকে ছেড়ে যায় (কেবলমাত্র ছোঁড়া যায় এমন সমস্ত ক্রিয়াকলাপ সফলভাবে সম্পন্ন হয়ে গেলে মেমরিটিকে হ্রাস করে))। একটি সহজ সমাধান হ'ল অনুলিপি আইডিয়ামটি অনুলিপি করুন।
মার্টিন ইয়র্ক

আপনার কাছে নীচে থেকে শার্পতুথ তৃতীয় লাইন রয়েছে delete stored[];এবং আমি বিশ্বাস করি এটি হওয়া উচিতdelete [] stored;
পিটার আজতাই

4
আমি জানি এটি কেবল একটি উদাহরণ, তবে আপনার আরও ভাল সমাধানটি ব্যবহার করা উচিত std::string। সাধারণ ধারণাটি হ'ল সংস্থানগুলি পরিচালনা করে এমন একমাত্র ইউটিলিটি ক্লাসগুলিকে বিগ থ্রিকে ওভারলোড করা দরকার এবং অন্য সমস্ত শ্রেণীর কেবলমাত্র সেই তিনটি ইউটিলিটি ক্লাস ব্যবহার করা উচিত, বিগ থ্রিগুলির কোনওটির সংজ্ঞা দেওয়ার প্রয়োজনীয়তা অপসারণ করা উচিত।
GManNickG

4
@ মার্টিন: আমি এটি নিশ্চিত করতে চেয়েছিলাম যে এটি পাথরে খোদাই করা হয়েছে। : পি
GManNickG

46

আমি কিছুটা বিদ্ধ হয়েছি যে এর নিয়মটি Rule of Fiveউদ্ধৃত হয়নি।

এই নিয়মটি খুব সাধারণ:

পাঁচটির নিয়ম :
আপনি যখনই ডিস্ট্র্রাক্টর, কপি কনস্ট্রাক্টর, কপি অ্যাসাইনমেন্ট অপারেটর, মুভ কনস্ট্রাক্টর বা মুভ অ্যাসাইনমেন্ট অপারেটর যেকোন একটিতে লিখছেন আপনার সম্ভবত অন্য চারটি লিখতে হবে।

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

প্রতিটি উত্স একটি উত্সর্গীকৃত অবজেক্ট দ্বারা পরিচালনা করা উচিত

এখানে @sharptoothকোডটি এখনও (বেশিরভাগ) জরিমানা, তবে তিনি যদি তার শ্রেণিতে দ্বিতীয় বৈশিষ্ট্য যুক্ত করেন তবে তা হবে না। নিম্নলিখিত শ্রেণীর বিবেচনা করুন:

class Erroneous
{
public:
  Erroneous();
  // ... others
private:
  Foo* mFoo;
  Bar* mBar;
};

Erroneous::Erroneous(): mFoo(new Foo()), mBar(new Bar()) {}

new Barছুড়ে মারলে কী হয় ? আপনি কীভাবে নির্দেশিত অবজেক্টটি মুছবেন mFoo? সমাধান রয়েছে (ফাংশন স্তরের চেষ্টা / ধরা ...), সেগুলি কেবল স্কেল করে না।

পরিস্থিতি মোকাবিলার সঠিক উপায় হ'ল কাঁচা পয়েন্টার পরিবর্তে যথাযথ ক্লাস ব্যবহার করা।

class Righteous
{
public:
private:
  std::unique_ptr<Foo> mFoo;
  std::unique_ptr<Bar> mBar;
};

একই কনস্ট্রাক্টর বাস্তবায়নের সাথে (বা আসলে, ব্যবহার করে make_unique), আমার কাছে এখন বিনামূল্যে ব্যতিক্রমী সুরক্ষা আছে !!! এটা কি উত্তেজনাপূর্ণ নয়? এবং সর্বোপরি, আমাকে আর কোনও সঠিক ধ্বংসকারী সম্পর্কে উদ্বিগ্ন হওয়ার দরকার নেই! আমার নিজের লেখার দরকার আছে Copy Constructorএবং Assignment Operatorযদিও, কারণunique_ptr এই ক্রিয়াকলাপগুলি সংজ্ঞায়িত করা হয় না ... তবে এখানে এটি কোনও ব্যাপার নয়;)

এবং তাই, sharptoothএর শ্রেণী পুনর্বিবেচিত:

class Class
{
public:
  Class(char const* str): mData(str) {}
private:
  std::string mData;
};

আমি আপনার সম্পর্কে জানি না, তবে আমি আমার পক্ষে আরও সহজ মনে করি;)


সি ++ 11 এর জন্য - পাঁচটির বিধি যা তিনটি মুভ কনস্ট্রাক্টর এবং মুভ অ্যাসাইনমেন্ট অপারেটরের বিধি যুক্ত করে।
রবার্ট অ্যান্ড্রেজুক

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

নিবন্ধন করুন সম্মত :-) আমি পাঁচটির নিয়ম উল্লেখ করেছি, যেহেতু এই উত্তরটি C ++ 11 এর আগে এবং "বিগ থ্রি" দিয়ে শুরু হয় তবে এটি উল্লেখ করা উচিত যে এখন "বিগ ফাইভ" প্রাসঙ্গিক। আমি এই উত্তরটি ভোট দিতে চাই না, কারণ এটি জিজ্ঞাসিত প্রসঙ্গে সঠিক।
রবার্ট আন্দ্রেজুক

@ রব: ভাল কথা, আমি বিগ থ্রি-র পরিবর্তে পাঁচটির বিধি উল্লেখ করার উত্তরটি আপডেট করেছি। আশাকরি বেশিরভাগ লোক এখন অবধি C ++ 11 সক্ষম সংকলকগুলিতে চলে গেছে (এবং যারা এখনও করেন নি তাদের প্রতি আমি মমতা করি)।
ম্যাথিউ এম।

31

আমি আমার অনুশীলন থেকে প্রত্যাহার করতে পারি এবং নিম্নলিখিত বিষয়গুলি নিয়ে ভাবতে পারি যখন কাউকে অনুলিপি সহকারে অনুলিপি নির্ধারণ / সংজ্ঞায়নের সাথে ডিল করতে হয়। আমি মামলা দুটি গ্রুপে বিভক্ত করেছি

  • সঠিকতা / শব্দার্থবিজ্ঞান - যদি আপনি কোনও ব্যবহারকারী-সংজ্ঞায়িত অনুলিপি-নির্মাণকারী সরবরাহ না করেন তবে এই ধরণের ব্যবহার করে প্রোগ্রামগুলি সংকলন করতে ব্যর্থ হতে পারে বা ভুলভাবে কাজ করতে পারে।
  • অপ্টিমাইজেশন - সংকলক উত্পাদিত অনুলিপি নির্মাণকারীকে একটি ভাল বিকল্প সরবরাহ করা প্রোগ্রামটিকে দ্রুততর করতে দেয়।


সঠিকতা / শব্দার্থবিজ্ঞান

আমি এই বিভাগে এমন মামলাগুলি রাখি যেখানে কপির নির্মাণকারীর ঘোষণার / সংজ্ঞা দেওয়া সেই ধরণের ব্যবহার করে প্রোগ্রামগুলির সঠিক ক্রিয়াকলাপের জন্য প্রয়োজনীয়।

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

সি ++ 03 এ ক্লাসটি কীভাবে অনুলিপিযোগ্য করা যায়

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

সি ++ 11 বা আরও নতুনতে কীভাবে কোনও ক্লাসটি অনুলিপিযোগ্য করা যায়

কপি-কনস্ট্রাক্টরটি =deleteশেষে ঘোষণা করুন ।


অগভীর বনাম ডিপ কপি

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

  • অস্থায়ী ফাইলগুলি ডিস্কে অনুলিপি করা হচ্ছে
  • একটি পৃথক নেটওয়ার্ক সংযোগ খোলার
  • একটি পৃথক কর্মী থ্রেড তৈরি
  • একটি পৃথক ওপেনএল ফ্রেমবফার বরাদ্দ করা হচ্ছে
  • ইত্যাদি

স্ব-নিবন্ধকরণ বস্তু

একটি শ্রেণীর বিবেচনা করুন যেখানে সমস্ত অবজেক্ট - সেগুলি কীভাবে নির্মান করা হয়েছে - তা কোনওভাবে নিবন্ধিত হওয়া উচিত। কিছু উদাহরণ:

  • সবচেয়ে সহজ উদাহরণ: বর্তমানে বিদ্যমান অবজেক্টের মোট গণনা বজায় রাখা। অবজেক্ট রেজিস্ট্রেশন স্ট্যাটিক কাউন্টারকে বাড়ানোর প্রায়।

  • আরও জটিল উদাহরণটির মধ্যে রয়েছে সিঙ্গলটন রেজিস্ট্রি, যেখানে সেই ধরণের বিদ্যমান সমস্ত বস্তুর উল্লেখ সংরক্ষণ করা হয় (যাতে বিজ্ঞপ্তিগুলি তাদের সকলের কাছে সরবরাহ করা যায়)।

  • রেফারেন্স গণনা করা স্মার্ট-পয়েন্টারগুলিকে এই বিভাগে কেবল একটি বিশেষ ক্ষেত্রে হিসাবে বিবেচনা করা যেতে পারে: নতুন পয়েন্টার একটি বৈশ্বিক রেজিস্ট্রি না করে ভাগ করে নেওয়া সংস্থান দ্বারা নিজেকে "রেজিস্ট্রি" করে।

এ জাতীয় স্ব-নিবন্ধকরণ অপারেশন অবশ্যই প্রকারের যে কোনও নির্মাণকারীর দ্বারা করা উচিত এবং অনুলিপি নির্মাণকারীও এর ব্যতিক্রম নয়।


অভ্যন্তরীণ ক্রস-রেফারেন্স সহ অবজেক্টগুলি

কিছু কিছু অবজেক্টের ভিন্ন ভিন্ন সাব-অবজেক্টের মধ্যে সরাসরি ক্রস-রেফারেন্স সহ অ-তুচ্ছ অভ্যন্তরীণ কাঠামো থাকতে পারে (বাস্তবে, কেবল এই জাতীয় একটি অভ্যন্তরীণ ক্রস-রেফারেন্সই এই ক্ষেত্রে ট্রিগার করার জন্য যথেষ্ট)। কম্পাইলার প্রদত্ত কপি কন্সট্রাকটর অভ্যন্তরীণ ভঙ্গ করবে ভিতরে-বস্তুর সমিতি, তাদের রূপান্তর আন্ত বস্তুর সমিতি।

একটি উদাহরণ:

struct MarriedMan;
struct MarriedWoman;

struct MarriedMan {
    // ...
    MarriedWoman* wife;   // association
};

struct MarriedWoman {
    // ...
    MarriedMan* husband;  // association
};

struct MarriedCouple {
    MarriedWoman wife;    // aggregation
    MarriedMan   husband; // aggregation

    MarriedCouple() {
        wife.husband = &husband;
        husband.wife = &wife;
    }
};

MarriedCouple couple1; // couple1.wife and couple1.husband are spouses

MarriedCouple couple2(couple1);
// Are couple2.wife and couple2.husband indeed spouses?
// Why does couple2.wife say that she is married to couple1.husband?
// Why does couple2.husband say that he is married to couple1.wife?

কিছু নির্দিষ্ট মানদণ্ড পূরণকারী বস্তুগুলিকেই অনুলিপি করার অনুমতি দেওয়া হয়

সেখানে ক্লাস যখন কিছু রাজ্যের (যেমন ডিফল্ট-নির্মাণ-স্টেট) এবং যেখানে বস্তু কপি করতে নিরাপদ হতে পারে না নিরাপদ অন্যথায় কপি করতে। যদি আমরা নিরাপদে-অনুলিপি করা অবজেক্টগুলি অনুলিপি করার অনুমতি দিতে চাই, তবে - যদি ডিফেন্সিয়ালি প্রোগ্রামিং হয় - আমাদের ব্যবহারকারী-সংজ্ঞায়িত অনুলিপি নির্মাণকারীর একটি রান-টাইম চেক প্রয়োজন।


অনুলিপিযোগ্য উপ-অবজেক্ট

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


আধা-অনুলিপি উপ-বস্তু

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

উদাহরণস্বরূপ, অবজেক্টের স্ব-নিবন্ধকরণের ক্ষেত্রে পুনর্বিবেচনা করা, আমরা যুক্তি দিতে পারি যে এমন পরিস্থিতি থাকতে পারে যেখানে কোনও অবজেক্ট বৈশ্বিক অবজেক্ট ম্যানেজারের সাথে নিবন্ধিত হতে হবে কেবলমাত্র যদি এটি সম্পূর্ণ স্ট্যান্ডেলোন অবজেক্ট হয়। যদি এটি অন্য কোনও অবজেক্টের সাব-অবজেক্ট হয়, তবে এটির পরিচালনার দায়িত্ব এটির অন্তর্ভুক্ত অবজেক্টের সাথে।

অথবা, অগভীর এবং গভীর উভয় অনুলিপিই সমর্থন করা উচিত (তাদের কোনওটিই ডিফল্ট নয়)।

তারপরে চূড়ান্ত সিদ্ধান্তটি সেই ধরণের ব্যবহারকারীদের কাছে রেখে যায় - যখন বিষয়গুলি অনুলিপি করা হয়, তাদের অবশ্যই অনুলিপি করার অনিচ্ছাকৃত পদ্ধতিটি স্পষ্টভাবে (অতিরিক্ত যুক্তির মাধ্যমে) নির্দিষ্ট করতে হবে।

প্রোগ্রামিংয়ের ক্ষেত্রে অরক্ষামূলক পদ্ধতির ক্ষেত্রে, এটিও সম্ভব যে নিয়মিত অনুলিপি-নির্মাতা এবং একটি কোটির-অনুলিপি-নির্মাণকারী উভয়ই উপস্থিত থাকেন। এটি ন্যায্য হতে পারে যখন বিশাল সংখ্যাগরিষ্ঠ ক্ষেত্রে একক অনুলিপি পদ্ধতি প্রয়োগ করা উচিত, যখন বিরল তবে বোঝা যায় পরিস্থিতিতে বিকল্প অনুলিপি পদ্ধতি ব্যবহার করা উচিত। তারপরে সংকলকটি অভিযোগ করবে না যে এটি অনুলিপিভাবে অনুলিপি নির্ধারণ করতে অক্ষম; এই ধরণের একটি সাব-অবজেক্টটি অর্ধ-অনুলিপি-নির্মাণকারীর মাধ্যমে অনুলিপি করা উচিত কিনা তা যাচাই করা এবং তা পরীক্ষা করা ব্যবহারকারীদের একমাত্র দায়িত্ব responsibility


অবজেক্টের পরিচয়ের সাথে দৃ associated়ভাবে জড়িত রাষ্ট্রের অনুলিপি করবেন না

বিরল ক্ষেত্রে অবজেক্টের পর্যবেক্ষণযোগ্য রাষ্ট্রের একটি উপসেট অবজেক্টের পরিচয়ের একটি অবিচ্ছেদ্য অংশ গঠন করতে পারে (বা বিবেচনা করা যেতে পারে) এবং অন্যান্য বস্তুর কাছে স্থানান্তরযোগ্য হওয়া উচিত নয় (যদিও এটি কিছুটা বিতর্কিত হতে পারে)।

উদাহরণ:

  • অবজেক্টের ইউআইডি (তবে এটি একটিও "স্ব-নিবন্ধকরণ" কেসটির সাথে সম্পর্কিত, যেহেতু স্ব-নিবন্ধনের কোনও আইডিতে আইডিটি অবশ্যই পাওয়া উচিত)।

  • যখন নতুন বস্তুটি উত্স অবজেক্টের ইতিহাসের উত্তরাধিকারী না হয় তবে অবজেক্টের ইতিহাস (উদাহরণস্বরূপ পূর্বাবস্থায় / পুনরায় স্ট্যাক) তার পরিবর্তে একক ইতিহাসের আইটেমটি দিয়ে শুরু করুন " <TIME> এ <OTHER_OBJECT_ID> থেকে অনুলিপি করা হয়েছে "।

এই জাতীয় ক্ষেত্রে অনুলিপি নির্মাণকারী অবশ্যই সংশ্লিষ্ট সাব-অবজেক্টগুলি অনুলিপি করে এড়িয়ে যেতে হবে।


অনুলিপি নির্মাণকারীর সঠিক স্বাক্ষর প্রয়োগ করা

সংকলক-সরবরাহকৃত অনুলিপি নির্মাণকারীর স্বাক্ষর নির্ভর করে সাব-অবজেক্টগুলির জন্য কপির কন্সট্রাক্টরগুলি উপলভ্য। যদি কমপক্ষে একটি সাব-অবজেক্টে সত্যিকারের অনুলিপি নির্মাণকারী না থাকে (ধ্রুবক রেফারেন্সের সাহায্যে উত্স অবজেক্ট গ্রহণ করা হয়) তবে পরিবর্তে একটি মিউটিং মিটিং কপি-কনস্ট্রাক্টর থাকে (অ-ধ্রুবক রেফারেন্স দ্বারা উত্স অবজেক্ট গ্রহণ করা হয়) তবে সংকলকের কোনও বিকল্প থাকবে না তবে সুস্পষ্টভাবে ঘোষণা এবং তারপরে পরিবর্তনীয় অনুলিপি-নির্ধারককে সংজ্ঞায়িত করতে।

এখন, যদি সাব-অবজেক্টের ধরণের "মিউটটিং" কপি-কনস্ট্রাক্টরটি উত্স অবজেক্টটি বাস্তবে রূপান্তরিত না করে (এবং কেবল এমন প্রোগ্রামার দ্বারা লিখেছিলেন যিনি constকীওয়ার্ড সম্পর্কে জানেন না )? যদি আমরা সেই কোডটি নিখোঁজ যুক্ত করে সংশোধন করতে না পারি const, তবে অন্য বিকল্পটি হ'ল আমাদের নিজস্ব ব্যবহারকারী-সংজ্ঞায়িত অনুলিপি নির্ধারককে একটি সঠিক স্বাক্ষর সহ ঘোষণা করা এবং একটিতে পরিণত হওয়ার পাপ করা const_cast


অনুলিপি (COW)

এমন একটি COW ধারক যা তার অভ্যন্তরীণ ডেটাতে সরাসরি রেফারেন্স দিয়েছে, নির্মাণের সময় গভীর কপি করা উচিত, অন্যথায় এটি রেফারেন্স গণনা হ্যান্ডেল হিসাবে আচরণ করতে পারে।

যদিও সিডাব্লু একটি অপ্টিমাইজেশনের কৌশল, এটি সঠিক প্রয়োগের জন্য অনুলিপি নির্মাণকারীতে এই যুক্তি অত্যন্ত গুরুত্বপূর্ণ। সে কারণেই আমি এই মামলাটি এখানে "অপটিমাইজেশন" বিভাগের চেয়ে রেখেছি, যেখানে আমরা পরের দিকে যাই।



অপ্টিমাইজেশন

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


কপির সময় কাঠামো অপ্টিমাইজেশন

এমন একটি ধারক বিবেচনা করুন যা উপাদান অপসারণ ক্রিয়াকলাপগুলিকে সমর্থন করে তবে মুছে ফেলা উপাদানটিকে কেবল মুছে ফেলা হিসাবে চিহ্নিত করে এবং পরে এর স্লটটি পুনরায় ব্যবহার করে। যখন এই ধরণের ধারকটির একটি অনুলিপি তৈরি করা হয়, তখন "মুছে ফেলা" স্লটগুলি যেমন সংরক্ষণ করা হয় তার চেয়ে বেঁচে থাকা ডেটা কমপ্যাক্ট করা বুদ্ধিমান হতে পারে।


অন-পর্যবেক্ষণযোগ্য স্থিতি অনুলিপি করা এড়িয়ে যান

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

এই অপটিমাইজেশনটি কেবলমাত্র যদি পর্যবেক্ষণযোগ্য রাষ্ট্রের প্রতিনিধিত্বকারী ডেটার তুলনায় সহায়ক ডেটা বড় হয় তবে তা ন্যায়সঙ্গত হয়।


অন্তর্নিহিত অনুলিপি অক্ষম করুন

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

সি ++ 03 এ একটি অনুলিপি নির্মাণকারীকে এটির সংজ্ঞা দেওয়ারও প্রয়োজন (অবশ্যই আপনি যদি এটি ব্যবহারের উদ্দেশ্যে রেখেছিলেন)। সুতরাং, কেবল আলোচিত উদ্বেগের বাইরে এইরকম একটি অনুলিপি নির্মাণকারীর জন্য যাওয়ার অর্থ হ'ল আপনাকে একই কোডটি লিখতে হয়েছিল যা সংকলক স্বয়ংক্রিয়ভাবে আপনার জন্য তৈরি করবে।

সি ++ 11 এবং আরও নতুন মান ডিফল্ট বাস্তবায়নটি ব্যবহারের জন্য স্পষ্ট অনুরোধের সাথে বিশেষ সদস্য ফাংশনগুলি (ডিফল্ট এবং অনুলিপি নির্মাণকারী, অনুলিপি-অপারেটর অপারেটর এবং ডেস্ট্রাক্টর) ঘোষণা করার অনুমতি দেয় (কেবলমাত্র এর সাথে ঘোষণাটি শেষ করুন =default)।



TODOs

এই উত্তরটি নিম্নরূপে উন্নত করা যেতে পারে:

  • আরও উদাহরণ কোড যোগ করুন
  • "অভ্যন্তরীণ ক্রস-রেফারেন্স সহ অবজেক্টস" কে চিত্রিত করুন
  • কিছু লিঙ্ক যুক্ত করুন

6

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

আপনাকে একটি অনুলিপি নির্মাণকারী লিখতে হবে যা title = new char[length+1]তারপরে করে strcpy(title, titleIn)। অনুলিপি নির্মাণকারী কেবল একটি "অগভীর" অনুলিপি করবেন।


2

অনুলিপি কনস্ট্রাক্টরকে ডাকা হয় যখন কোনও বস্তু হয় হয় মান দ্বারা পাস হয়, মান দ্বারা ফেরত দেওয়া হয় বা স্পষ্টভাবে অনুলিপি করা হয়। যদি কোনও অনুলিপি নির্মাণকারী না থাকে, সি ++ একটি ডিফল্ট অনুলিপি নির্মাণকারী তৈরি করে যা অগভীর অনুলিপি তৈরি করে। যদি বস্তুর গতিময় বরাদ্দ মেমরিটির কোনও পয়েন্টার না থাকে তবে অগভীর অনুলিপিটি করবে।


0

ক্লাস বিশেষভাবে এটির প্রয়োজন না হলে অনুলিপি করা অনুলিপি এবং অপারেটর = অক্ষম করা প্রায়শই ভাল ধারণা। রেফারেন্সের উদ্দেশ্যে যখন মান দ্বারা একটি আর্গ পাস করার মতো এটি অদক্ষতাগুলি আটকাতে পারে। সংকলক উত্পন্ন পদ্ধতি অবৈধ হতে পারে।


-1

কোড স্নিপেট নীচে বিবেচনা করা যাক:

class base{
    int a, *p;
public:
    base(){
        p = new int;
    }
    void SetData(int, int);
    void ShowData();
    base(const base& old_ref){
        //No coding present.
    }
};
void base :: ShowData(){
    cout<<this->a<<" "<<*(this->p)<<endl;
}
void base :: SetData(int a, int b){
    this->a = a;
    *(this->p) = b;
}
int main(void)
{
    base b1;
    b1.SetData(2, 3);
    b1.ShowData();
    base b2 = b1; //!! Copy constructor called.
    b2.ShowData();
    return 0;
}

Output: 
2 3 //b1.ShowData();
1996774332 1205913761 //b2.ShowData();

b2.ShowData();জাঙ্ক আউটপুট দেয় কারণ সেখানে একটি ব্যবহারকারী-সংজ্ঞায়িত কপি-কনস্ট্রাক্টর রয়েছে যা ডেটা স্পষ্টভাবে অনুলিপি করার জন্য কোনও কোড লেখা নেই। সুতরাং সংকলক একই তৈরি করে না।

আপনার জ্ঞানটি আপনার সবার সাথে ভাগ করে নেওয়ার কথা ভেবেছিলেন, যদিও আপনার বেশিরভাগ এটি ইতিমধ্যে জানেন।

চিয়ার্স ... হ্যাপি কোডিং !!!

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