সি ++ এ কন্সট্রাক্টর এবং = অপারেটর ওভারলোড কপি করুন একটি সাধারণ কাজ সম্ভব?


87

যেহেতু একটি অনুলিপি নির্মাণকারী

MyClass(const MyClass&);

এবং একটি = অপারেটর ওভারলোড

MyClass& operator = (const MyClass&);

প্রায় একই কোড, একই প্যারামিটার এবং কেবল ফেরতের ক্ষেত্রে পৃথক রয়েছে, তাদের উভয়ের ব্যবহারের পক্ষে কি একটি সাধারণ ফাংশন থাকা সম্ভব?


6
"... অনেকটা একই কোড আছে ..."? হুম ... আপনি অবশ্যই কিছু ভুল করছেন। এর জন্য ব্যবহারকারীর দ্বারা সংজ্ঞায়িত ফাংশনগুলি ব্যবহার করার প্রয়োজনটিকে ছোট করার চেষ্টা করুন এবং সংকলকটিকে সমস্ত নোংরা কাজটি করতে দিন। এর অর্থ প্রায়শই তাদের নিজস্ব সদস্য অবজেক্টে সংযুক্তি সংস্থান থাকে। আপনি আমাদের কিছু কোড দেখাতে পারেন হয়তো আমাদের কিছু ভাল নকশার পরামর্শ রয়েছে।
বিক্রয়বিটজে

উত্তর:


123

হ্যাঁ. দুটি সাধারণ বিকল্প আছে। একটি - যা সাধারণত নিরুৎসাহিত হয় - তা operator=অনুলিপি দ্বারা অনুলিপি নির্মাণকারী থেকে কল করা :

MyClass(const MyClass& other)
{
    operator=(other);
}

যাইহোক, operator=পুরানো রাষ্ট্রের সাথে কাজ করার ক্ষেত্রে এবং স্ব-নিয়োগের ফলে উদ্ভূত সমস্যাগুলির ক্ষেত্রে ভাল সরবরাহ সরবরাহ করা একটি চ্যালেঞ্জ। এছাড়াও, সমস্ত সদস্য এবং ঘাঁটিগুলি পূর্বের থেকে নির্ধারিত হওয়া সত্ত্বেও প্রথমে ডিফল্ট সূচনা হয় other। এটি এমনকি সমস্ত সদস্য এবং ঘাঁটিগুলির পক্ষেও বৈধ হতে পারে এবং এটি বৈধ যেখানে এমনকি এটি অর্থহীনভাবে অপ্রয়োজনীয় এবং ব্যবহারিকভাবে ব্যয়বহুলও হতে পারে।

একটি ক্রমবর্ধমান জনপ্রিয় সমাধান হ'ল operator=অনুলিপি নির্মাণকারী এবং একটি অদলবদল পদ্ধতি ব্যবহার করে প্রয়োগ করা।

MyClass& operator=(const MyClass& other)
{
    MyClass tmp(other);
    swap(tmp);
    return *this;
}

অথবা এমনকি:

MyClass& operator=(MyClass other)
{
    swap(other);
    return *this;
}

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

অনুলিপি এবং অদলবদ আইডিয়ামের উপকারিতা হ'ল এটি স্বয়ংক্রিয়ভাবে স্ব-কার্যনির্বাহী নিরাপদ এবং - যে সোয়াপ অপারেশনটি নো-থ্রো না দেওয়া রয়েছে - তাও দৃ strongly়ভাবে ব্যতিক্রম নিরাপদ।

দৃ strongly়ভাবে ব্যতিক্রম নিরাপদ হতে, একটি 'হাত' লিখিত কার্যনির্বাহক অপারেটরকে সাধারণত Assignee এর পুরানো সম্পদগুলি ডি-বরাদ্দ করার আগে নতুন সংস্থার একটি অনুলিপি বরাদ্দ করতে হয় যাতে যদি কোনও ব্যতিক্রম নতুন সংস্থানগুলি বরাদ্দ ঘটে, তবে পুরানো রাষ্ট্রটি আবার ফিরে যেতে পারে । এগুলি সমস্ত কিছুই অনুলিপি-অন-স্বাপের সাথে নিখরচায় আসে তবে সাধারণত এটি আরও জটিল এবং তাই স্ক্র্যাচ থেকে করার জন্য ত্রুটি প্রবণ।

যে বিষয়টির প্রতি সাবধানতা অবলম্বন করতে হবে তা হ'ল সোয়াপ পদ্ধতিটি সত্যিকারের সোয়াপ, এবং std::swapসেই অনুলিপিটি নয় যা অনুলিপি নির্মাণকারী এবং অ্যাসাইনমেন্ট অপারেটর নিজেই ব্যবহার করে।

সাধারণত সদস্য swapহিসাবে ব্যবহৃত হয়। std::swapসমস্ত বেসিক ধরণের এবং পয়েন্টার ধরণের সাথে গ্যারান্টিযুক্ত এবং 'নো-থ্রো' কাজ করে। বেশিরভাগ স্মার্ট পয়েন্টারগুলিকে নো-থ্রো গ্যারান্টি দিয়েও পরিবর্তন করা যায়।


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

14
হতে পারে "আমি প্রস্তাব দিই না", যুক্ত করুন "এবং কোনও সি ++ বিশেষজ্ঞও করেন না"। কেউ আসতে পারে এবং বুঝতে ব্যর্থ হতে পারে যে আপনি কেবল একটি ব্যক্তিগত সংখ্যালঘু পছন্দকেই প্রকাশ করছেন না, যারা প্রকৃতপক্ষে এটি সম্পর্কে চিন্তাভাবনা করেছেন তাদের মীমাংসিত sensকমত্য মতামত। এবং, ঠিক আছে, সম্ভবত আমি ভুল এবং কিছু সি ++ বিশেষজ্ঞ এটির প্রস্তাব দিচ্ছেন, তবে ব্যক্তিগতভাবে আমি সেই সুপারিশটির জন্য কোনও রেফারেন্স নিয়ে আসার জন্য কাউকে গন্টলেটটি রেখে দিয়েছিলাম।
স্টিভ জেসপ

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

4
+1 এবং আমি মনে করি প্রয়োজনের সবসময় বিশ্লেষণ থাকে। আমি মনে করি যে কোনও assignকোনও ক্ষেত্রে (লাইটওয়েট ক্লাসের জন্য) অনুলিপি কর্টর এবং অ্যাসাইনমেন্ট অপারেটর উভয়ই সদস্য ফাংশন ব্যবহার করা যুক্তিসঙ্গত বলে মনে করি । অন্যান্য ক্ষেত্রে (সংস্থার নিবিড় / কেসগুলি হ্যান্ডেল / বডি ব্যবহার করে) অনুলিপি / সোয়াপ দেওয়া অবশ্যই যেতে হবে।
জোহানেস স্কাউব -

4
@ লিটব: আমি এতে অবাক হয়েছি তাই আমি ব্যতিক্রম সি ++ এ আইটেম 41 সন্ধান করলাম (যা এটি রূপান্তরিত হয়েছিল) এবং এই বিশেষ প্রস্তাবটি চলে গেছে এবং তিনি তার জায়গায় অনুলিপি-অদলবদল করার পরামর্শ দিয়েছেন। বরং গোপনে তিনি একই সাথে "সমস্যা # 4: এটি নিয়োগের পক্ষে অক্ষম" ফেলে দিয়েছেন।
সিবি বেইলি

14

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

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

swapচার্লস প্রস্তাবিত হিসাবে আজকাল যা প্রচলিত আইডিয়োমকে সাধারণত বিবেচনা করা হয় তা ব্যবহার করছে :

MyClass& operator=(MyClass other)
{
    swap(other);
    return *this;
}

এটি অনুলিপি-নির্মাণ (নোটটি otherঅনুলিপি করা হয়েছে) এবং ধ্বংস (এটি ফাংশন শেষে ধ্বংস করা হয়েছে) ব্যবহার করে - এবং এটি সেগুলি সঠিক ক্রমেও ব্যবহার করে: ধ্বংসের পূর্বে নির্মাণ (ব্যর্থ হতে পারে) (অবশ্যই ব্যর্থ হবে না)।


করা উচিত swapঘোষিত virtual?

4
@ জোহানেস: ভার্চুয়াল ফাংশনগুলি বহুমুখী শ্রেণীর শ্রেণিবিন্যাসে ব্যবহৃত হয়। অ্যাসাইনমেন্ট অপারেটরগুলি মান ধরণের জন্য ব্যবহৃত হয়। দুজনেই খুব মেশে।
এসবিআই

-3

কিছু আমাকে বিরক্ত করে:

MyClass& operator=(const MyClass& other)
{
    MyClass tmp(other);
    swap(tmp);
    return *this;
}

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

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

সুতরাং, আমি আরও কিছু প্রাকৃতিক "স্থানান্তর" করার জন্য "অদলবদলের" পরিবর্তে প্রস্তাব দিই:

MyClass& operator=(const MyClass& other)
{
    MyClass tmp(other);
    transfer(tmp);
    return *this;
}

অস্থায়ী অবজেক্টটির এখনও নির্মাণ রয়েছে, তবে পরবর্তী তাত্ক্ষণিক ক্রিয়া হ'ল গন্তব্যের সমস্ত বর্তমান সংস্থানগুলি সরিয়ে নেওয়ার আগে (এবং NULLing যাতে তারা দ্বিগুণ-মুক্ত হবে না) উত্সটির উত্সগুলি সরবরাহ করা।

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

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

অদলবদলের পরিবর্তে স্থানান্তর করুন। এটা যাইহোক আমার পরামর্শ।


4
একজন ডেস্ট্রাক্টর অবশ্যই ব্যর্থ হবেন না, সুতরাং ধ্বংসের পরে ব্যতিক্রমগুলি আশা করা যায় না। এবং, আমি পাচ্ছি না যে পদক্ষেপটি সবচেয়ে বিপজ্জনক অপারেশন হলে ধ্বংসের পেছনে সরানোর সুবিধা কী হবে? উদাহরণস্বরূপ, স্ট্যান্ডার্ড স্কিমে, একটি সরানো ব্যর্থতা পুরানো রাষ্ট্রকে দূষিত করবে না, যেখানে আপনার নতুন স্কিমটি করে। তাহলে কেন? এছাড়াও, First, reading the word "swap" when my mind is thinking "copy" irritates-> একটি গ্রন্থাগার লেখক হিসাবে আপনি সাধারণত প্রচলিত অভ্যাসগুলি (অনুলিপি + সোয়াপ) জানেন এবং ক্রুজটি হ'ল my mind। আপনার মন আসলে পাবলিক ইন্টারফেসের আড়ালে লুকিয়ে আছে। পুনরায় ব্যবহারযোগ্য কোডটি এটাই।
সেবাস্তিয়ান মাচ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.