C ++ এ "কনস্ট" এর ব্যবহার কয়টি এবং কোনটি?


129

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


ঠিক সেই প্রশ্নের সন্ধান করছেন: ডি
আলামীন

উত্তর:


100

কিছু ব্যবহার সংগ্রহ করার চেষ্টা করছেন:

কিছুটা অস্থায়ীকে রেফারেন্স-টু-কনস্টেটিংয়ের জন্য বেঁধে দেওয়া, এর জীবনকাল দীর্ঘায়িত করতে। রেফারেন্সটি বেস হতে পারে - এবং এটির ডেস্ট্রাক্টরকে ভার্চুয়াল হওয়ার দরকার নেই - ডান ডাস্ট্রাস্টরকে এখনও বলা হয়:

ScopeGuard const& guard = MakeGuard(&cleanUpFunction);

কোড ব্যবহার করে ব্যাখ্যা :

struct ScopeGuard { 
    ~ScopeGuard() { } // not virtual
};

template<typename T> struct Derived : ScopeGuard { 
    T t; 
    Derived(T t):t(t) { }
    ~Derived() {
        t(); // call function
    }
};

template<typename T> Derived<T> MakeGuard(T t) { return Derived<T>(t); }

এই কৌশলটি আলেকজান্দ্রেস্কুর স্কোপগার্ড ইউটিলিটি ক্লাসে ব্যবহৃত হয়। অস্থায়ী সুযোগের বাইরে চলে গেলে ডেরাইভের ডেস্ট্রাক্টরকে সঠিকভাবে ডাকা হয়। উপরের কোডটি কিছু ছোট বিবরণ মিস করে তবে এটির সাথে এটিই বড় চুক্তি।


অন্যদের বলার জন্য কনড ব্যবহার করুন পদ্ধতিগুলি এই বস্তুর লজিকাল অবস্থার পরিবর্তন করবে না।

struct SmartPtr {
    int getCopies() const { return mCopiesMade; }
};

কপিরাইট অন লেখার ক্লাসগুলির জন্য কনস্ট ব্যবহার করুন, সংকলক আপনাকে কখন এবং কখন অনুলিপি করতে হবে না তা সিদ্ধান্ত নিতে সহায়তা করে।

struct MyString {
    char * getData() { /* copy: caller might write */ return mData; }
    char const* getData() const { return mData; }
};

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

কোড ব্যবহার :

int main() {
    string const a = "1234";
    string const b = a;
    // outputs the same address for COW strings
    cout << (void*)&a[0] << ", " << (void*)&b[0];
}

উপরের স্নিপেটটি আমার জিসিসিতে একই ঠিকানাটি মুদ্রণ করে, কারণ ব্যবহৃত সি ++ গ্রন্থাগার একটি অনুলিপি অনুলিপি প্রয়োগ করে std::string। উভয় স্ট্রিং, যদিও তারা স্বতন্ত্র বস্তু, তাদের স্ট্রিং ডেটার জন্য একই মেমরি ভাগ করে। bনন-কনস্ট্যান্ট তৈরি করা নন-কনস্ট্যান্ট সংস্করণটিকে পছন্দ করবে operator[]এবং জিসিসি ব্যাকিং মেমোরি বাফারের একটি অনুলিপি তৈরি করবে, কারণ আমরা এটি পরিবর্তন করতে পারি এবং এটির ডেটা প্রভাবিত করতে হবে না a!

int main() {
    string const a = "1234";
    string b = a;
    // outputs different addresses!
    cout << (void*)&a[0] << ", " << (void*)&b[0];
}

অনুলিপি বস্তু এবং টেম্পোরারিগুলি থেকে অনুলিপি তৈরির জন্য অনুলিপি-নির্মাতার জন্য :

struct MyClass {
    MyClass(MyClass const& that) { /* make copy of that */ }
};

ধ্রুবকভাবে পরিবর্তন করতে পারে না এমন ধ্রুবক তৈরির জন্য

double const PI = 3.1415;

মান ব্যতীত রেফারেন্সের মাধ্যমে স্বেচ্ছাচারিত বস্তুগুলি পাস করার জন্য - সম্ভবত ব্যয়বহুল বা অসম্ভবকে বাই-মান পাস করা রোধ করতে

void PrintIt(Object const& obj) {
    // ...
}

2
আপনি উদাহরণস্বরূপ প্রথম এবং তৃতীয় ব্যবহার দয়া করে ব্যাখ্যা করতে পারেন?
টিউনুজ

"কলিকে গ্যারান্টি দেওয়ার জন্য যে প্যারামিটারটি নুল হতে পারে না" আমি দেখতে পাচ্ছি না কনস্টের উদাহরণটির সাথে কীভাবে কিছু করার আছে।
লোগান ক্যাপালডো

ওফ, আমি তাই ব্যর্থ। আমি একরকম রেফারেন্স সম্পর্কে লিখতে শুরু করি।
হাহাকার করার

3
প্রথম উদাহরণটি ব্যাখ্যা করুন। আমাকে খুব একটা বোঝায় না।
চিকুবা

28

সি ++ তে কনস্টের 2 টি মূল ব্যবহার রয়েছে।

কনস্ট মান

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

void PrintStudent(const Student& student) {
  cout << student.GetName();
}

আপনি কেন এটি করবেন তা হিসাবে। যদি আপনি জানেন যে অন্তর্নিহিত ডেটা পরিবর্তন করতে পারে না তবে অ্যালগরিদম সম্পর্কে যুক্তিযুক্ত হওয়া অনেক সহজ। "কনস্ট" সহায়তা করে, তবে এটি অর্জনের গ্যারান্টি দেয় না।

স্পষ্টতই, কাউটে ডেটা মুদ্রণের জন্য খুব বেশি চিন্তাভাবনার দরকার নেই :)

কনস্ট্যান্ট হিসাবে কোনও সদস্য পদ্ধতি চিহ্নিত করা

পূর্ববর্তী উদাহরণে আমি ছাত্রকে কনস্ট হিসাবে চিহ্নিত করেছি। কিন্তু সি ++ কীভাবে জানল যে শিক্ষার্থীর উপর getName () পদ্ধতি কল করা অবজেক্টটিকে রূপান্তরিত করতে পারে না? উত্তরটি হল যে পদ্ধতিটি কনস্ট হিসাবে চিহ্নিত করা হয়েছিল।

class Student {
  public:
    string GetName() const { ... }
};

একটি পদ্ধতি "কনস্ট" চিহ্নিত করা 2 টি কাজ করে। প্রাথমিকভাবে এটি সি ++ কে বলে যে এই পদ্ধতিটি আমার অবজেক্টটিকে পরিবর্তন করবে না। দ্বিতীয়টি হ'ল সমস্ত সদস্যের ভেরিয়েবলগুলি এখন এমন আচরণ করা হবে যেন সেগুলি কনস্ট হিসাবে চিহ্নিত করা হয়েছিল। এটি আপনাকে সহায়তা করে কিন্তু আপনার শ্রেণীর উদাহরণটি পরিবর্তন করতে বাধা দেয় না।

এটি একটি অত্যন্ত সাধারণ উদাহরণ তবে আশা করি এটি আপনার প্রশ্নের জবাব দিতে সহায়তা করবে।


16

এই 4 টি ঘোষণার মধ্যে পার্থক্যটি বোঝার যত্ন নিন:

নিম্নলিখিত 2 ঘোষণাগুলি শব্দার্থগতভাবে অভিন্ন। আপনি সিসিপি 1 এবং সিসিপি 2 পয়েন্ট যেখানে পরিবর্তন করতে পারেন তবে তারা যে জিনিসটিতে ইঙ্গিত করছেন তা আপনি পরিবর্তন করতে পারবেন না।

const char* ccp1;
char const* ccp2;

এরপরে, পয়েন্টারটি কনস্ট, সুতরাং অর্থবোধক হওয়ার জন্য এটি কোনও কিছুর দিকে নির্দেশ করতে হবে। আপনি এটিকে অন্য কোনও কিছুর দিকে নির্দেশ করতে পারবেন না, তবে যে বিষয়টিকে এটি নির্দেশ করেছে তা পরিবর্তন করা যেতে পারে।

char* const cpc = &something_possibly_not_const;

পরিশেষে, আমরা দুটি একত্রিত করি - সুতরাং নির্দেশিত জিনিসটি পরিবর্তন করা যায় না এবং পয়েন্টারটি অন্য কোথাও নির্দেশ করতে পারে না।

const char* const ccpc = &const_obj;

ঘড়ির কাঁটার সর্পিল নিয়ম একটি ঘোষণাকে আনুষ্ঠানিকভাবে সহায়তা করতে পারে http://c-faq.com/decl/spiral.anderson.html


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

3

একটি সামান্য নোট হিসাবে, আমি এখানে পড়া হিসাবে , এটি লক্ষ্য করা দরকারী

const তার তাত্ক্ষণিক বাম দিকে যা আছে তার উপর প্রযোজ্য (যদি সেখানে তার কিছু না ঘটে তবে তা তার তত্ক্ষণিক ডানদিকে যা প্রযোজ্য তা বাদ দিয়ে))

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