'মিউটেবল' কীওয়ার্ডটির কনস্ট ফাংশন দ্বারা ভেরিয়েবলটি পরিবর্তন করার অনুমতি ব্যতীত অন্য কোনও উদ্দেশ্য রয়েছে কি?


527

কিছুক্ষণ আগে আমি এমন কিছু কোড পেলাম যা mutableকীওয়ার্ড সহ কোনও শ্রেণীর সদস্য ভেরিয়েবল চিহ্নিত করেছিল । আমি যতদূর দেখতে পাচ্ছি এটিকে সহজভাবে আপনাকে কোনও constপদ্ধতিতে ভেরিয়েবল পরিবর্তন করতে সহায়তা করে :

class Foo  
{  
private:  
    mutable bool done_;  
public:  
    void doSomething() const { ...; done_ = true; }  
};

এটি কি এই কীওয়ার্ডের একমাত্র ব্যবহার বা এটি চোখের সাক্ষাতের চেয়ে আরও বেশি কিছু? আমি তখন থেকে এই কৌশলটি ক্লাসে ব্যবহার করেছি, এটি একটি boost::mutexথিতু const-সুরক্ষা কারণে ফাংশনটিকে এটি লক করতে সক্ষম হিসাবে একটি পরিবর্তনীয় হিসাবে চিহ্নিত করে , তবে সত্যি বলতে কী, এটি কিছুটা হ্যাকের মতো অনুভব করে।


2
একটি প্রশ্ন যদিও আপনি যদি কিছু সংশোধন না করে থাকেন তবে আপনাকে প্রথমে কেন একটি মুটেক্স ব্যবহার করা দরকার? আমি শুধু এটি বুঝতে চাই।
মিসেজভোলিউশন

@ মিসভোলিউশন আপনি কোনও কিছু সংশোধন করছেন, আপনি কেবল নিয়ন্ত্রণ করছেন যে কারা / কীভাবে কনস্টের মাধ্যমে সংশোধন করতে পারে। একটি সত্যই নিখুঁত উদাহরণ, কল্পনা করুন যে আমি যদি কেবল বন্ধুদের নন-কনস্ট্যান্ট হ্যান্ডলগুলি দিয়ে থাকি, শত্রুরা কনস্টের হ্যান্ডেল পায়। বন্ধুরা সংশোধন করতে পারে, শত্রুরা পারে না।
ইহানেই

1
দ্রষ্টব্য: এখানে কীওয়ার্ডটি ব্যবহারের একটি দুর্দান্ত উদাহরণ রয়েছে mutable: stackoverflow.com/questions/15999123/…
গ্যাব্রিয়েল স্ট্যাপলস

আমি আশা করি এটি const(ধরণের ধরণের) ওভাররাইড হিসাবে ব্যবহৃত হতে পারে তাই আমার এটি করার দরকার নেই class A_mutable{}; using A = A_mutable const; mutable_t<A> a;:, যদি আমি কনস্ট-বাই-ডিফল্ট, অর্থাৎ mutable A a;(সুস্পষ্ট রূপান্তরযোগ্য) এবং A a;(অন্তর্নিহিত কনস্ট) চাই।
alfC

উত্তর:


351

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

যেহেতু সি ++ 11 mutableল্যাম্বডায় ব্যবহার করা যেতে পারে তা বোঝাতে যে মান দ্বারা ক্যাপচার করা জিনিসগুলি পরিবর্তনযোগ্য (তারা ডিফল্টরূপে নয়):

int x = 0;
auto f1 = [=]() mutable {x = 42;};  // OK
auto f2 = [=]()         {x = 42;};  // Error: a by-value capture cannot be modified in a non-mutable lambda

52
'পরিবর্তনযোগ্য' মোটেই বিটওয়াইজ / লজিক্যাল স্থিরতা প্রভাবিত করে না। সি ++ কেবল বিটওয়াইজ কনস্ট এবং এই চেকিং থেকে সদস্যদের বাদ দেওয়ার জন্য 'পরিবর্তনযোগ্য' কীওয়ার্ড ব্যবহার করা যেতে পারে। অ্যাবস্ট্রাকশন (উদাঃ স্মার্টপ্যাটার্স) বাদে সি ++ তে 'লজিক্যাল' কনস্টের অর্জন সম্ভব নয়।
রিচার্ড কর্ডেন

111
@ রিচার্ড: আপনি পয়েন্টটি মিস করছেন। কোনও "লজিকাল কনস্ট" কীওয়ার্ড নেই, সত্য, বরং এটি একটি ধারণামূলক পার্থক্য যা প্রোগ্রামার সিদ্ধান্ত নিতে পারে যে কোন সদস্যকে পরিবর্তনের যোগ্য করে বাদ দেওয়া উচিত, কোন বস্তুর যৌক্তিক পর্যবেক্ষণযোগ্য রাষ্ট্রের গঠন বোঝার ভিত্তিতে।
টনি ডেলরয়

6
@ জায়ে হ্যাঁ, এটি কনস্টেট অবজেক্টে পরিবর্তিত হতে দেওয়ার জন্য কোনও সদস্যকে পরিবর্তনীয় হিসাবে পরিবর্তনশীল হিসাবে চিহ্নিত করার পুরো পয়েন্ট।
কিথবি

6
ল্যাম্বডাসে কেন একজনের পরিবর্তনীয় প্রয়োজন? রেফারেন্স অনুসারে ভেরিয়েবল ক্যাপচার করা কি যথেষ্ট হবে না?
জর্জিও

11
@ জর্জিও: পার্থক্যটি হ'ল ল্যাম্বদার xঅভ্যন্তরে পরিবর্তিত ল্যাম্বদার মধ্যেই থাকে, অর্থাৎ ল্যাম্বডা ফাংশনটি কেবল তার নিজস্ব অনুলিপি পরিবর্তন করতে পারে x। পরিবর্তনটি বাইরে দৃশ্যমান নয়, আসলটি xএখনও অপরিবর্তিত। বিবেচনা করুন যে ল্যাম্বডাসগুলি ফান্টারের শ্রেণি হিসাবে প্রয়োগ করা হয়; ক্যাপচারড ভেরিয়েবল সদস্য ভেরিয়েবলের সাথে মিল রাখে।
সেবাস্তিয়ান মাচ

138

mutableশব্দ বিঁধান একটি উপায় constঘোমটা আপনি আপনার বস্তু উপর সাজান। আপনার যদি কোনও অবজেক্টের কাছে স্থির রেফারেন্স বা পয়েন্টার থাকে তবে কখন এবং কীভাবে চিহ্নিত রয়েছে তা বাদ দিয়ে আপনি কোনওভাবেই সেই অবজেক্টটি সংশোধন করতে পারবেন না mutable

আপনার constরেফারেন্স বা পয়েন্টার দিয়ে আপনি সীমাবদ্ধ:

  • যে কোনও দৃশ্যমান ডেটা সদস্যের জন্য কেবল অ্যাক্সেস পড়ুন
  • চিহ্নিত পদ্ধতিগুলিতে কেবল কল করার অনুমতি const

mutableব্যতিক্রম এটা তোলে যাতে আপনি এখন লিখতে বা সেট ডেটার সদস্যরা চিহ্নিত করা হয়েছে পারবেন mutable। এটিই কেবল বাহ্যিকভাবে দৃশ্যমান পার্থক্য।

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

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

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

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


8
এছাড়াও, const_castকোনও সামগ্রীর একটি অংশকে সংশোধন করতে ব্যবহার করা constঅনির্ধারিত আচরণের ফল দেয়।
ব্রায়ান

আমি এর সাথে একমত নই কারণ এটি এপিআই ক্লায়েন্টকে অবজেক্টগুলির প্রতিরক্ষা সুরক্ষা ধ্বংস করতে বাধ্য করে । আপনি ব্যবহার ছিল const_castএকটি সদস্য ভেরিয়েবল পরিবর্তন বাস্তবায়ন constপদ্ধতি, আপনি ক্লায়েন্ট ঢালাই করতে বলি না - আপনি এটি করতে চাই পদ্ধতি মধ্যে দ্বারা const_casting this। মূলত এটি আপনি একটি সময়ে নির্বিচারে সদস্যদের উপর constness বাইপাস করতে দেয় নির্দিষ্ট কল সাইটে , যখন mutableআপনাকে একটি উপর const অপসারণ এর নির্দিষ্ট সদস্য সব কল সাইট এ। আধুনিকটি সাধারণত আপনি সাধারণত ব্যবহারের জন্য যা চান (ক্যাশিং, পরিসংখ্যান) তবে কখনও কখনও কনস্ট_কাস্ট প্যাটার্নে ফিট করে।
BeeOnRope

1
const_castপ্যাটার্ন হইয়া যেমন যখন আপনি সাময়িকভাবে সদস্য পরিবর্তন করতে চান যেমন কিছু ক্ষেত্রে, ভাল করে, তাহলে এটি পুনঃস্থাপন (প্রায় কাছাকাছি মত boost::mutex)। চূড়ান্ত অবস্থা প্রাথমিকের সমান হওয়ায় পদ্ধতিটি যৌক্তিকভাবে সংহত, তবে আপনি সেই ক্ষণস্থায়ী পরিবর্তন করতে চান। const_castসেখানে কার্যকর হতে পারে কারণ এটি আপনাকে সেই পদ্ধতিতে বিশেষভাবে দূরে সরিয়ে দেয় যদি আপনি রূপান্তরটি পূর্বাবস্থায় ফিরে mutableআসেন তবে এটি যথাযথ হবে না কারণ এটি সমস্ত পদ্ধতি থেকে দৃ const় সুরক্ষা অপসারণ করবে , যা অগত্যা সকলেই "অনুসরণ করে না" , পূর্বাবস্থায় ফিরুন।
BeeOnRope

2
কনড সংজ্ঞায়িত অবজেক্টের প্লে - ওনল মেমরির (সম্ভবত সাধারণত মেমরি কেবল পঠনযোগ্য হিসাবে চিহ্নিত করা হয় ) এবং সম্পর্কিত মানক ভাষায় এটির সম্ভাব্য স্থান নির্ধারণের ফলে এটি const_castএকটি সম্ভাব্য সময়-বোমা তৈরি করে। mutableএই জাতীয় বিষয়গুলি কেবল পঠনযোগ্য মেমরিতে রাখা যায়নি বলে এ জাতীয় কোনও সমস্যা নেই।
BeeOnRope

75

আপনার বুস্ট :: মুটেক্স সহ আপনার ব্যবহার হ'ল এই কীওয়ার্ডটি ঠিক কীসের জন্য। অন্য ব্যবহার হ'ল গতি অ্যাক্সেসে অভ্যন্তরীণ ফলাফল ক্যাশে করার জন্য।

মূলত, 'পরিবর্তনযোগ্য' কোনও শ্রেণীর বৈশিষ্ট্যের ক্ষেত্রে প্রযোজ্য যা বস্তুর বাহ্যিক দৃশ্যমান স্থিতিকে প্রভাবিত করে না।

আপনার প্রশ্নের নমুনা কোডে, পরিবর্তনযোগ্য অনুপযুক্ত হতে পারে যদি সম্পন্ন_এর মান বহিরাগত অবস্থাকে প্রভাবিত করে, এটি যা আছে তার উপর নির্ভর করে ...; অংশ।


35

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

http://www.highprogrammer.com/alan/rants/mutable.html

সুতরাং উপরোক্ত উন্মাদনা যদি পরিবর্তনের জন্য উপযুক্ত না হয় তবে এটি কীসের জন্য? এখানে সূক্ষ্ম ক্ষেত্রে: পরিবর্তনযোগ্য হ'ল ক্ষেত্রে কোনও ক্ষেত্রে যুক্তিযুক্তভাবে ধ্রুবক হয় তবে বাস্তবে পরিবর্তিত হওয়া দরকার। এই কেসগুলি খুব কম এবং এর মধ্যে খুব বেশি তবে এটি বিদ্যমান।

লেখক উদাহরণস্বরূপ ক্যাশিং এবং অস্থায়ী ডিবাগিং ভেরিয়েবলগুলি অন্তর্ভুক্ত করে।


2
আমি মনে করি এই লিঙ্কটি এমন একটি দৃশ্যের সর্বোত্তম উদাহরণ দেয় যেখানে পরিবর্তনীয় সহায়ক I এটি প্রায়শই প্রদর্শিত হয় যেগুলি কেবলমাত্র ডিবাগিংয়ের জন্য ব্যবহৃত হয়। (যথাযথ ব্যবহারের জন্য)
উত্সাহী

এর ব্যবহার mutableকোডটি আরও পঠনযোগ্য এবং পরিষ্কার করতে পারে। নিম্নলিখিত উদাহরণে, প্রত্যাশার মতো readহতে constপারে। `পরিবর্তনীয় m_mutex; ধারক m_container; অকার্যকর অ্যাড (আইটেম আইটেম) ock লকগার্ড লক (m_mutex); m_container.pushback (আইটেম); Read আইটেম পড়ুন () কনস্ট {লকগার্ড লক (m_mutex); রিটার্ন m_container.first (); } `
থ। থাইলেমান

একটি অত্যন্ত জনপ্রিয় ব্যবহারের কেস রয়েছে: রেফ গণনা করা।
সেবা আলেকসেয়েভ

33

এটি এমন পরিস্থিতিতে কার্যকর যেখানে আপনার অভ্যন্তরীণ অবস্থা যেমন ক্যাশে লুকিয়ে রয়েছে। উদাহরণ স্বরূপ:

ক্লাস হ্যাশ টেবিল
{
...
প্রকাশ্য:
    স্ট্রিং লুক (স্ট্রিং কী) কনস্ট
    {
        যদি (কী == সর্বশেষ)
            সর্বশেষ মূল্য ফেরান;

        স্ট্রিং ভ্যালু = লুকিংইন্টার্নাল (কী);

        lastKey = কী;
        সর্বশেষমূল্য = মান;

        ফেরত মূল্য;
    }

ব্যক্তিগত:
    পরিবর্তনীয় স্ট্রিং লাস্টকি, লাস্টভ্যালু;
};

এবং তারপরে আপনি কোনও const HashTableবস্তু এখনও তার lookup()পদ্ধতিটি ব্যবহার করতে পারেন যা অভ্যন্তরীণ ক্যাশে পরিবর্তন করে।


9

mutable আপনি অন্যথায় ধ্রুবক ক্রিয়ায় ডেটা পরিবর্তন করার অনুমতি দেওয়ার জন্য অনুমিত হিসাবে উপস্থিত রয়েছে।

উদ্দেশ্যটি হ'ল আপনার কোনও ফাংশন থাকতে পারে যা বস্তুর অভ্যন্তরীণ অবস্থার সাথে "কিছুই করে না", এবং তাই আপনি ফাংশনটি চিহ্নিত করেন const, তবে আপনাকে সত্যিকার অর্থে কিছু অবজেক্টের এমন কিছু পরিবর্তন করতে হবে যা এর সঠিক প্রভাব ফেলবে না might কার্যকারিতা।

মূলশব্দটি সংকলকের প্রতি ইঙ্গিত হিসাবে কাজ করতে পারে - একটি তাত্ত্বিক সংকলক মেমরিতে একটি ধ্রুবক বস্তু (যেমন একটি গ্লোবাল) রাখতে পারে যা কেবলমাত্র পঠনযোগ্য হিসাবে চিহ্নিত হয়েছিল। mutableইঙ্গিতগুলির উপস্থিতি যা এটি করা উচিত নয়।

পরিবর্তনীয় ডেটা ঘোষণা ও ব্যবহার করার জন্য এখানে কিছু বৈধ কারণ রয়েছে:

  • থ্রেড সুরক্ষা। একটি ঘোষণা mutable boost::mutexপুরোপুরি যুক্তিসঙ্গত।
  • পরিসংখ্যান। কিছু বা সমস্ত আর্গুমেন্ট প্রদত্ত কোনও ফাংশনে কলগুলির সংখ্যা গণনা করা।
  • Memoization। কিছু ব্যয়বহুল উত্তর গণনা করা, এবং তারপরে এটি পুনরায় পুনরায় সংখ্যার চেয়ে ভবিষ্যতের রেফারেন্সের জন্য সংরক্ষণ করা।

2
"উত্তেজনাপূর্ণ" ইস্যু সম্পর্কিত বিষয়ে মন্তব্য ছাড়া ভাল উত্তর answer এটি দেখে মনে হচ্ছে যেন কোনও পরিবর্তনকারী সদস্য কখনও কখনও পরিবর্তন করতে পারবেন না যদি সংকলকটি বস্তুটি রমের মধ্যে রাখে। পরিবর্তনীয় আচরণ ভাল সংজ্ঞা দেওয়া হয়।
রিচার্ড কর্ডেন

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

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

এখন, কিছু সংকলকের বিশেষ এক্সটেনশন রয়েছে যেমন জিসিসির _ট্রিবিউট __ ((কনস্ট)) এবং __ট্রিবিউট __ ((খাঁটি)), যা এরকম প্রভাব ফেলেছে , তবে এটি কেবলমাত্র constসি ++ এর কীওয়ার্ডের সাথে সম্পর্কিত ।
BeeOnRope

8

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

class CIniWrapper
{
public:
   CIniWrapper(LPCTSTR szIniFile);

   // non-const: logically modifies the state of the object
   void SetValue(LPCTSTR szName, LPCTSTR szValue);

   // const: does not logically change the object
   LPCTSTR GetValue(LPCTSTR szName, LPCTSTR szDefaultValue) const;

   // ...

private:
   // cache, avoids going to disk when a named value is retrieved multiple times
   // does not logically change the public interface, so declared mutable
   // so that it can be used by the const GetValue() method
   mutable std::map<string, string> m_mapNameToValue;
};

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


6

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

উল্লিখিত পরিবর্তনীয় উভয়টি সংকলক এবং পাঠককে অবহিত করে যে এটি নিরাপদ এবং প্রত্যাশা করা হয়েছে যে কোনও সদস্যের ভেরিয়েবল একটি কনস্ট সদস্যের কার্যক্রমে পরিবর্তিত হতে পারে।


4

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


4

এটির আপনার ব্যবহার হ্যাক নয়, যদিও সি ++++ এর অনেক কিছুর মতো, মিটিবল এমন একটি অলস প্রোগ্রামারকে হ্যাক করা যেতে পারে যিনি পুরোপুরি ফিরে যেতে চান না এবং এমন কিছু চিহ্নিত করতে চান যা কন-কনস্ট্যান্ট না হওয়া উচিত।


3

ব্যবহারকারীদের কাছে যৌক্তিকভাবে রাষ্ট্রবিহীন জিনিসগুলির জন্য "পরিবর্তনযোগ্য" ব্যবহার করুন (এবং এইভাবে পাবলিক ক্লাসের 'এপিআইগুলিতে "কনস্ট" প্রাপ্ত হওয়া উচিত) তবে অন্তর্নিহিত কার্যকরকরণ (আপনার .cpp এর কোড) এ রাজ্যহীন নয়।

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


2

পরিবর্তনীয় constক্লাসের জন্য বিটওয়াইজ কনস্ট থেকে লজিক্যাল কনস্টের অর্থ পরিবর্তন করে ।

এর অর্থ এই যে পরিবর্তিত সদস্যদের সহ ক্লাসগুলি আর বিটওয়াস কনস্ট হবে এবং এক্সিকিউটেবলের কেবল পঠনযোগ্য বিভাগে আর উপস্থিত হবে না।

তদ্ব্যতীত, এটি constসদস্য ফাংশনগুলি ব্যবহার না করে পরিবর্তিত সদস্য পরিবর্তন করার অনুমতি দিয়ে টাইপ-চেকিংয়ে পরিবর্তন করে const_cast

class Logical {
    mutable int var;

public:
    Logical(): var(0) {}
    void set(int x) const { var = x; }
};

class Bitwise {
    int var;

public:
    Bitwise(): var(0) {}
    void set(int x) const {
        const_cast<Bitwise*>(this)->var = x;
    }
};

const Logical logical; // Not put in read-only.
const Bitwise bitwise; // Likely put in read-only.

int main(void)
{
    logical.set(5); // Well defined.
    bitwise.set(5); // Undefined.
}

আরও তথ্যের জন্য অন্যান্য উত্তরগুলি দেখুন তবে আমি হাইলাইট করতে চেয়েছিলাম যে এটি কেবল টাইপ-সাফটির জন্য নয় এবং এটি সংকলিত ফলাফলকে প্রভাবিত করে।


1

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

এটি আমার কাছে বেশিরভাগ সময় হ্যাকের মতো অনুভূত হয়। খুব খুব কম পরিস্থিতিতে কার্যকর।


1

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

সাধারণভাবে, mutableকীওয়ার্ডটি ব্যবহারের বিকল্পগুলি সাধারণত পদ্ধতি বা কৌশলটিতে স্থির পরিবর্তনশীল const_cast

আরেকটি বিস্তারিত ব্যাখ্যা এখানে রয়েছে


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

1
@ ফ্রেসনেল "স্ট্যাটিক ভেরিয়েবল" দ্বারা আমার অর্থ পদ্ধতিতে স্ট্যাটিক স্বয়ংক্রিয় ভেরিয়েবলগুলি (যেগুলি কলগুলির বাইরে থাকে)। এবং const_castকোনও constপদ্ধতিতে শ্রেণীর সদস্যকে সংশোধন করতে ব্যবহার করা যেতে পারে , যা আমি উল্লেখ করেছি ...
ড্যানিয়েল হার্শকোভিচ

1
এটি আমার কাছে পরিষ্কার ছিল না, যেমন আপনি "সাধারণভাবে" লিখেছেন :) এর মাধ্যমে সংশোধন করার ক্ষেত্রে const_cast, যেমনটি বলা হয়েছিল কেবল তখনই এটি অনুমোদিত যখন বস্তুটি ঘোষণা করা হয়নি const। উদাহরণস্বরূপ const Frob f; f.something();, অপরিবর্তিত void something() const { const_cast<int&>(m_foo) = 2;আচরণের ফলাফল সহ ।
সেবাস্তিয়ান মাচ

1

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


1

শ্রেণি পরীক্ষার উদ্দেশ্যে স্টাবগুলি তৈরি করার সময় পরিবর্তনীয় কীওয়ার্ডটি খুব কার্যকর। আপনি কোনও কনস্টেন্ট ফাংশন আটকে রাখতে পারেন এবং এখনও আপনার স্টাবটিতে যে পরিমাণ পরীক্ষা কার্যকারিতা যুক্ত করেছেন তা বাড়ানোর (পরিবর্তনযোগ্য) কাউন্টার বা সক্ষম করতে পারবেন। এটি স্ট্যাবড শ্রেণীর ইন্টারফেস অক্ষত রাখে।


0

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

mutableস্টোরেজ ক্লাসটি কেবলমাত্র কোনও শ্রেণীর নন স্ট্যাটিক নন কনস্টেট ডেটা সদস্যের জন্য ব্যবহার করা যায়। কোনও শ্রেণীর মিউটেবল ডেটা সদস্যকে পরিবর্তন করা যেতে পারে এমনকি যদি এটি কোনও বস্তুর অংশ যা কনস্ট হিসাবে ঘোষণা করা হয়।

class Test
{
public:
    Test(): x(1), y(1) {};
    mutable int x;
    int y;
};

int main()
{
    const Test object;
    object.x = 123;
    //object.y = 123;
    /* 
    * The above line if uncommented, will create compilation error.
    */   

    cout<< "X:"<< object.x << ", Y:" << object.y;
    return 0;
}

Output:-
X:123, Y:1

উপরের উদাহরণে, আমরা সদস্য ভেরিয়েবলের মান পরিবর্তন করতে সক্ষম হব xযদিও এটি কোনও বস্তুর অংশ যা কনস্ট হিসাবে ঘোষিত হয়। এটি কারণ ভেরিয়েবলকে পরিবর্তনযোগ্য xহিসাবে ঘোষণা করা হয়। তবে আপনি যদি সদস্য ভেরিয়েবলের মান সংশোধন করার চেষ্টা করেন তবে yসংকলক একটি ত্রুটি ছুঁড়ে দেবে।


-1

খুব কীওয়ার্ড 'মিউটেবল' আসলে একটি সংরক্ষিত কীওয়ার্ড ofফেটেনেন্ট হিসাবে এটি ধ্রুবক ভেরিয়েবলের মান পরিবর্তিত করতে ব্যবহৃত হয় f আপনি যদি কনসেন্টের একাধিক মান রাখতে চান তবে কীওয়ার্ডটি পরিবর্তনীয় ব্যবহার করুন।

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