যেখানে কনস্টেন্ট পয়েন্টার অত্যন্ত প্রযোজ্য তার উদাহরণ এইভাবে প্রদর্শিত হতে পারে। এটির ভিতরে ডায়নামিক অ্যারে সহ আপনার একটি শ্রেণি রয়েছে তা বিবেচনা করুন এবং আপনি অ্যারেতে ব্যবহারকারীর অ্যাক্সেসটি পাস করতে চান তবে পয়েন্টারটি পরিবর্তনের অধিকার না দিয়ে তাদের ছাড় দিন। বিবেচনা:
#include <new>
#include <string.h>
class TestA
{
private:
char *Array;
public:
TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
~TestA(){if(Array != NULL){ delete [] Array;} }
char * const GetArray(){ return Array; }
};
int main()
{
TestA Temp;
printf("%s\n",Temp.GetArray());
Temp.GetArray()[0] = ' '; //You can still modify the chars in the array, user has access
Temp.GetArray()[1] = ' ';
printf("%s\n",Temp.GetArray());
}
যা উত্পাদন করে:
ইনপুট ডেটা
ডেটা রাখে
তবে আমরা যদি এটি চেষ্টা করি:
int main()
{
TestA Temp;
printf("%s\n",Temp.GetArray());
Temp.GetArray()[0] = ' ';
Temp.GetArray()[1] = ' ';
printf("%s\n",Temp.GetArray());
Temp.GetArray() = NULL; //Bwuahahahaa attempt to set it to null
}
আমরা পেতে:
ত্রুটি: অ্যাসাইনমেন্টের বাম অপারেন্ড হিসাবে লভ্যালু প্রয়োজন // ড্র্যাট আবার বানচাল!
সুতরাং পরিষ্কারভাবে আমরা অ্যারের সামগ্রীগুলি সংশোধন করতে পারি, তবে অ্যারের পয়েন্টারটি নয়। আপনি যদি ব্যবহারকারীকে ফেরত দেওয়ার সময় পয়েন্টারটির একটি সামঞ্জস্যপূর্ণ অবস্থা থাকে তা নিশ্চিত করতে চান তবে ভাল। একটি ধরা আছে, যদিও:
int main()
{
TestA Temp;
printf("%s\n",Temp.GetArray());
Temp.GetArray()[0] = ' ';
Temp.GetArray()[1] = ' ';
printf("%s\n",Temp.GetArray());
delete [] Temp.GetArray(); //Bwuahaha this actually works!
}
আমরা এখনও পয়েন্টারের মেমরি রেফারেন্স মুছতে পারি, এমনকি যদি আমরা পয়েন্টারটি নিজেই পরিবর্তন করতে না পারি।
সুতরাং আপনি যদি মেমরির রেফারেন্সটি সর্বদা কোনও কিছুর দিকে নির্দেশ করতে চান (IE কখনই পরিবর্তিত হবে না, বর্তমানে কোনও রেফারেন্স কীভাবে কাজ করে তার অনুরূপ), তবে এটি অত্যন্ত প্রযোজ্য। আপনি যদি চান যে ব্যবহারকারীর সম্পূর্ণ অ্যাক্সেস রয়েছে এবং এটি সংশোধন করতে পারে তবে অ-কনস্ট্যান্ট আপনার জন্য।
সম্পাদনা:
রাইট-ভ্যালু অপারেন্ড হওয়ার কারণে গেটআর ()) নির্ধারণ করতে সক্ষম না হওয়ায় Okorz001 মন্তব্যটি উল্লেখ করার পরে, তার মন্তব্য সম্পূর্ণ সঠিক, তবে উপরেরটি এখনও প্রযোজ্য যদি আপনি পয়েন্টারের কোনও রেফারেন্স ফিরিয়ে দেন (আমি মনে করি আমি গেটআরিকে ধরেছিলাম একটি রেফারেন্স উল্লেখ করে), উদাহরণস্বরূপ:
class TestA
{
private:
char *Array;
public:
TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
~TestA(){if(Array != NULL){ delete [] Array;} }
char * const &GetArray(){ return Array; } //Note & reference operator
char * &GetNonConstArray(){ return Array; } //Note non-const
};
int main()
{
TestA Temp;
Temp.GetArray() = NULL; //Returns error
Temp.GetNonConstArray() = NULL; //Returns no error
}
প্রথমটিতে কোনও ত্রুটির ফলে ফিরে আসবে:
ত্রুটি: কেবলমাত্র পঠনযোগ্য স্থান 'টেম্প.টেষ্টা :: গেটআরে ()' এর কার্যভার
তবে দ্বিতীয়টি নীচে সম্ভাব্য পরিণতি সত্ত্বেও আনন্দের সাথে ঘটবে।
স্পষ্টতই, প্রশ্ন উত্থাপিত হবে 'আপনি কেন কোনও পয়েন্টারের কোনও রেফারেন্স ফিরিয়ে দিতে চান'? এমন বিরল উদাহরণ রয়েছে যেখানে আপনাকে প্রশ্নটির মূল পয়েন্টারে সরাসরি মেমরি (বা ডেটা) অর্পণ করতে হবে (উদাহরণস্বরূপ, আপনার নিজের মালেক / ফ্রি বা নতুন / ফ্রি ফ্রন্ট-এন্ড তৈরি করা), তবে সেই দৃষ্টান্তে এটি একটি অবিসংবাদী রেফারেন্স reference । কনস্টেন্ট পয়েন্টারের একটি রেফারেন্স আমি এমন পরিস্থিতিটি পাইনি যা এটির ওয়ারেন্ট দেয় (যদি না প্রত্যাবর্তনের ধরণের পরিবর্তে কনস্ট রেফারেন্স ভেরিয়েবল হিসাবে ঘোষণা করা যায়)?
আমাদের যদি কোনও ফাংশন থাকে যা কনস্ট পয়েন্টার গ্রহণ করে (বনাম একটি যা না করে) বিবেচনা করুন:
class TestA
{
private:
char *Array;
public:
TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
~TestA(){if(Array != NULL){ delete [] Array;} }
char * const &GetArray(){ return Array; }
void ModifyArrayConst(char * const Data)
{
Data[1]; //This is okay, this refers to Data[1]
Data--; //Produces an error. Don't want to Decrement that.
printf("Const: %c\n",Data[1]);
}
void ModifyArrayNonConst(char * Data)
{
Data--; //Argh noo what are you doing?!
Data[1]; //This is actually the same as 'Data[0]' because it's relative to Data's position
printf("NonConst: %c\n",Data[1]);
}
};
int main()
{
TestA Temp;
Temp.ModifyArrayNonConst("ABCD");
Temp.ModifyArrayConst("ABCD");
}
কনস্টের ত্রুটিটি এইভাবে বার্তা দেয়:
ত্রুটি: কেবলমাত্র পঠনযোগ্য পরামিতি 'ডেটা' হ্রাস
যা আমরা সম্ভবত এটি করতে চাই না হিসাবে এটি ভাল, যদি না আমরা মন্তব্যগুলিতে চিহ্নিত সমস্যাগুলি তৈরি করতে চাই। যদি আমরা কনস্ট ফাংশনটির হ্রাস সম্পাদনা করি তবে নিম্নলিখিতটি ঘটে:
ননকনস্ট: এ কনস্ট্যান্ট:
বি
স্পষ্টতই, যদিও এ 'ডেটা [1]' হলেও এটি 'ডেটা [0]' হিসাবে বিবেচিত হচ্ছে কারণ ননকনস্ট পয়েন্টার হ্রাস ক্রিয়াকলাপের অনুমতি দিয়েছে। কনস্টের বাস্তবায়ন হওয়ার সাথে সাথে অন্য একজন লিখেছেন, সম্ভাব্য ত্রুটিটি হওয়ার আগে আমরা এটি ধরি।
অন্য একটি প্রধান বিবেচনা, হ'ল একটি কনস্ট পয়েন্টারটি সিউডো রেফারেন্স হিসাবে ব্যবহার করা যেতে পারে, এতে যে বিষয়টিকে রেফারেন্স নির্দেশ করে সেটি পরিবর্তন করা যায় না (এক আশ্চর্য, সম্ভবত এটি যদি এটি বাস্তবায়ন করা হত)। বিবেচনা:
int main()
{
int A = 10;
int * const B = &A;
*B = 20; //This is permitted
printf("%d\n",A);
B = NULL; //This produces an error
}
সংকলনের চেষ্টা করার সময়, নিম্নলিখিত ত্রুটিটি উত্পাদন করে:
ত্রুটি: কেবলমাত্র পঠনযোগ্য 'বি' এর অ্যাসাইনমেন্ট
এ সম্পর্কিত একটি ধ্রুবক রেফারেন্স চাইলে কোনটি সম্ভবত খারাপ জিনিস। যদি B = NULL
মন্তব্য করা হয়, সংকলকটি আনন্দের সাথে আমাদের সংশোধন করতে দেবে *B
এবং এ কারণেই এগুলি কৌতুকগুলির সাথে কার্যকর বলে মনে হচ্ছে না, তবে বিবেচনা করুন যে আপনি যদি এমন কোনও গ্রাফিকাল অ্যাপ্লিকেশনটির একক অবস্থান নিয়েছিলেন যেখানে আপনি অমার্জনযোগ্য পয়েন্টার চেয়েছিলেন যা আপনি পাশ করতে পারতেন কাছাকাছি.
এটির ব্যবহার পরিবর্তনশীল (অনিচ্ছাকৃত শ্লেষকে ক্ষমা করুন), তবে সঠিকভাবে ব্যবহৃত হয়েছে, প্রোগ্রামিংয়ে সহায়তা করার জন্য এটি বাক্সের অন্য একটি সরঞ্জাম।