আমি জানি রেফারেন্সগুলি সিনট্যাকটিক চিনি, তাই কোড পড়া এবং লেখা সহজ।
তবে পার্থক্য কী?
int &x = *(int*)0;
সিসিটিতে। রেফারেন্সটি আসলে নুলকে নির্দেশ করতে পারে।
আমি জানি রেফারেন্সগুলি সিনট্যাকটিক চিনি, তাই কোড পড়া এবং লেখা সহজ।
তবে পার্থক্য কী?
int &x = *(int*)0;
সিসিটিতে। রেফারেন্সটি আসলে নুলকে নির্দেশ করতে পারে।
উত্তর:
একটি পয়েন্টার পুনরায় বরাদ্দ করা যেতে পারে:
int x = 5;
int y = 6;
int *p;
p = &x;
p = &y;
*p = 10;
assert(x == 5);
assert(y == 10);
একটি রেফারেন্স পারে না, এবং প্রারম্ভিক সময়ে নির্ধারিত হতে হবে:
int x = 5;
int y = 6;
int &r = x;
একটি পয়েন্টারের স্ট্যাকের নিজস্ব মেমরি ঠিকানা এবং আকার থাকে (x86 এ 4 বাইট), যেখানে একটি রেফারেন্স একই মেমরি ঠিকানা ভাগ করে (মূল ভেরিয়েবল সহ) তবে স্ট্যাকের উপরে কিছু জায়গা নেয়। যেহেতু একটি রেফারেন্সের মূল ভেরিয়েবলের একই ঠিকানা থাকে, তাই একই ভেরিয়েবলের অন্য নাম হিসাবে কোনও রেফারেন্সটি ভাবা নিরাপদ। দ্রষ্টব্য: একটি পয়েন্টার পয়েন্ট কী স্ট্যাক বা গাদা হতে পারে। একটি রেফারেন্স। এই বিবৃতিতে আমার দাবিটি নয় যে কোনও পয়েন্টার অবশ্যই স্ট্যাকের দিকে নির্দেশ করবে। একটি পয়েন্টার কেবল একটি পরিবর্তনশীল যা একটি স্মৃতি ঠিকানা রাখে। এই ভেরিয়েবলটি স্ট্যাকের মধ্যে রয়েছে। যেহেতু একটি রেফারেন্সের স্ট্যাকের নিজস্ব স্থান রয়েছে এবং যেহেতু ঠিকানাটি তার উল্লেখযোগ্য পরিবর্তকের মত একই। আরো স্ট্যাক গাদা বনাম। এটি সূচিত করে যে এখানে একটি রেফারেন্সের আসল ঠিকানা রয়েছে যা সংকলক আপনাকে বলবে না।
int x = 0;
int &r = x;
int *p = &x;
int *p2 = &r;
assert(p == p2);
আপনার পয়েন্টারগুলিতে পয়েন্টারগুলিতে পয়েন্টারগুলিতে অতিরিক্ত মাত্রার ইন্ডিয়ারেশন প্রস্তাব করতে পারে। যদিও রেফারেন্সগুলি কেবলমাত্র এক স্তরের ইন্ডিয়ারেশনের প্রস্তাব দেয়।
int x = 0;
int y = 0;
int *p = &x;
int *q = &y;
int **pp = &p;
pp = &q;//*pp = q
**pp = 4;
assert(y == 4);
assert(x == 0);
একটি পয়েন্টার nullptr
সরাসরি বরাদ্দ করা যেতে পারে , যেখানে রেফারেন্স পারে না। যদি আপনি যথেষ্ট চেষ্টা করেন এবং আপনি কীভাবে জানেন তবে আপনি কোনও রেফারেন্সের ঠিকানাটি তৈরি করতে পারেন nullptr
। তেমনি, আপনি যদি যথেষ্ট চেষ্টা করেন তবে আপনার পয়েন্টারের একটি রেফারেন্স থাকতে পারে এবং তারপরে সেই উল্লেখটি থাকতে পারে nullptr
।
int *p = nullptr;
int &r = nullptr; <--- compiling error
int &r = *p; <--- likely no compiling error, especially if the nullptr is hidden behind a function call, yet it refers to a non-existent int at address 0
পয়েন্টারগুলি একটি অ্যারের উপরে পুনরাবৃত্তি করতে পারে; আপনি ++
পরবর্তী আইটেমটিতে যেতে পারেন যা একটি পয়েন্টারটি নির্দেশ করছে এবং + 4
5 তম উপাদানটিতে যেতে পারে। পয়েন্টারটি পয়েন্টারটি যে আকারের তা কোন বিষয় নয়।
কোনও পয়েন্টারটিকে *
মেমোরির অবস্থান নির্দেশ করার জন্য এটির সাথে ডিফারেন্স করা দরকার, যেখানে সরাসরি একটি রেফারেন্স ব্যবহার করা যেতে পারে। শ্রেণি / কাঠামোর একটি পয়েন্টার ->
এর সদস্যদের অ্যাক্সেস করতে ব্যবহার করে যেখানে একটি রেফারেন্স ব্যবহার করে .
।
রেফারেন্সগুলি একটি অ্যারেতে স্টাফ করা যায় না, তবে পয়েন্টারগুলি (ব্যবহারকারী @ লিটিব দ্বারা উল্লেখ করা) হতে পারে
কনস্টের রেফারেন্সগুলি অস্থায়ীভাবে আবদ্ধ হতে পারে। পয়েন্টারগুলি (কোনও দিকনির্দেশ ছাড়াই নয়):
const int &x = int(12); //legal C++
int *y = &int(12); //illegal to dereference a temporary.
এটি const&
আর্গুমেন্ট তালিকাগুলিতে ব্যবহারের জন্য আরও সুরক্ষিত করে।
একটি রেফারেন্সটি একটি ধ্রুবক পয়েন্টার হিসাবে বিবেচনা করা যেতে পারে (একটি ধ্রুবক মানের সাথে একটি পয়েন্টার দিয়ে বিভ্রান্ত হওয়ার দরকার নেই!) স্বয়ংক্রিয়ভাবে ইন্ডাইরিফিকেশন সহ, অর্থাৎ সংকলকটি *
আপনার জন্য অপারেটরটি প্রয়োগ করবে ।
সমস্ত রেফারেন্স অবশ্যই নন-নাল মান দিয়ে শুরু করতে হবে বা সংকলন ব্যর্থ হবে। কোনও রেফারেন্সের ঠিকানা পাওয়া সম্ভব নয় - ঠিকানার পরিবর্তে অ্যাড্রেস অপারেটর রেফারেন্সযুক্ত মানটির ঠিকানা ফিরিয়ে দেবে - বা রেফারেন্সগুলিতে পাটিগণিত করাও সম্ভব নয়।
সি প্রোগ্রামাররা সি ++ রেফারেন্সগুলি অপছন্দ করতে পারে কারণ ইন্ডিয়ারেশন যখন ঘটে তখন এটি আর স্পষ্ট হবে না বা যদি কোনও আর্গুমেন্ট মান দ্বারা বা বিন্দু দ্বারা ফাংশন স্বাক্ষরগুলি না দেখিয়ে পাস হয়ে যায়।
সি ++ প্রোগ্রামাররা পয়েন্টারগুলিকে অনিরাপদ হিসাবে বিবেচনা করা পছন্দ করতে পারে না - যদিও উল্লেখগুলি সবচেয়ে তুচ্ছ ঘটনা বাদে ধ্রুব পয়েন্টারগুলির চেয়ে কোনও নিরাপদ নয় - স্বয়ংক্রিয়ভাবে ইন্ডিরেশনের সুবিধার অভাব এবং ভিন্ন শব্দার্থক ধারণাটি বহন করে।
সি ++ এফএকিউ থেকে নিম্নলিখিত বিবৃতিটি বিবেচনা করুন :
যদিও অন্তর্নিহিত সমাবেশ ভাষায় কোনও ঠিকানা ব্যবহার করে একটি রেফারেন্স প্রায়শই প্রয়োগ করা হয় তবে দয়া করে কোনও বিষয়টিকে কোনও মজাদার চেহারা হিসাবে দেখবেন না । একটি রেফারেন্স হ'ল অবজেক্ট। এটি কোনও বস্তুর প্রতি নির্দেশক নয়, না কোনও বস্তুর অনুলিপিও। এটা তোলে হয় অবজেক্ট।
তবে যদি কোনও রেফারেন্স সত্যই অবজেক্ট হয় তবে কীভাবে এখানে রেফারেন্স থাকতে পারে? নিয়ন্ত্রিত ভাষায়, রেফারেন্সগুলির পক্ষে পয়েন্টারগুলির চেয়ে কোনও 'নিরাপদ' হওয়া অসম্ভব - সাধারণত স্কোপ সীমানা জুড়ে নির্ভরযোগ্যভাবে উপন্যাসের মানগুলির উপায় নেই!
একটি সি পটভূমি থেকে আসছে, সি ++ রেফারেন্স একটি কিছুটা নিরীহ ধারণা মত মনে হতে পারে, কিন্তু এক এখনো পয়েন্টার যেখানে সম্ভব পরিবর্তে তাদের ব্যবহার করা উচিত: স্বয়ংক্রিয় অপ্রত্যক্ষ্যতার হয় সুবিধাজনক, এবং রেফারেন্স সহায়ক হয়ে যখন সঙ্গে তার আচরণ RAII - কিন্তু কোন অনুভূত নিরাপত্তার কারণ সুবিধার্থে নয়, বরং তারা এডিয়োমেটিক কোড লেখাকে কম বিশ্রী করে তোলে।
আরআইআই হ'ল সি ++ এর অন্যতম কেন্দ্রীয় ধারণা, তবে এটি শব্দার্থবিজ্ঞানের অনুলিপি সহ অ-তুচ্ছভাবে মিথস্ক্রিয়া করে। কোনও অনুলিপি জড়িত না হওয়ায় রেফারেন্স সহ অবজেক্টগুলি পাস করা এই সমস্যাগুলি এড়িয়ে চলে। যদি ভাষাতে রেফারেন্স উপস্থিত না থাকত তবে আপনাকে পরিবর্তে পয়েন্টার ব্যবহার করতে হবে, যা ব্যবহার করা আরও জটিল, সুতরাং ভাষা ডিজাইনের নীতিটি লঙ্ঘন করে যে বিকল্পগুলির চেয়ে সেরা-অনুশীলন সমাধানটি সহজ হওয়া উচিত।
আপনি যদি সত্যই পেডেন্টিক হতে চান তবে একটি জিনিস যা আপনি একটি পয়েন্টার দিয়ে করতে পারবেন না এমন একটি রেফারেন্স সহ করতে পারেন: একটি অস্থায়ী বস্তুর আজীবন প্রসারিত করুন। সি ++ এ আপনি যদি কোনও অস্থায়ী অবজেক্টের জন্য একটি দৃ const় রেফারেন্স বেঁধে রাখেন তবে object বস্তুর আজীবন রেফারেন্সের আজীবন হয়ে যায়।
std::string s1 = "123";
std::string s2 = "456";
std::string s3_copy = s1 + s2;
const std::string& s3_reference = s1 + s2;
এই উদাহরণে s3_copy অস্থায়ী বস্তুটি অনুলিপি করে যা সংঘবদ্ধতার ফলাফল। যেখানে মূলত s3_references অস্থায়ী বস্তুতে পরিণত হয়। এটি সত্যিই একটি অস্থায়ী অবজেক্টের একটি রেফারেন্স যার রেফারেন্সটির এখনকার জীবনকাল।
আপনি যদি const
এটির চেষ্টা না করে এটি সংকলন করতে ব্যর্থ হওয়া উচিত। আপনি কোনও অস্থায়ী অবজেক্টের জন্য অবিচ্ছিন্ন রেফারেন্সকে বেঁধে রাখতে পারবেন না, আপনি এই বিষয়ে তার ঠিকানা নিতে পারবেন না।
const &
বাঁধাইয়ের সত্য দ্বারা প্রসারিত হয় , এবং কেবলমাত্র যখন রেফারেন্স সুযোগের বাইরে চলে যায় তখনই প্রকৃত রেফারেন্সযুক্ত ধরণের ডেস্ট্রাক্টর (রেফারেন্স টাইপের তুলনায়, এটি বেস হতে পারে) বলা হয়। যেহেতু এটি একটি রেফারেন্স, এর মধ্যে কোনও স্লাইসিং হবে না।
Animal x = fast ? getHare() : getTortoise()
পরে থাকে তবে x
ক্লাসিক স্লাইসিং সমস্যার মুখোমুখি হবেন, যখন Animal& x = ...
সঠিকভাবে কাজ করবে।
সিনট্যাকটিক চিনি ছাড়াও, একটি রেফারেন্স একটি const
পয়েন্টার ( কোনওটির দিকে নির্দেশক নয়const
)। আপনি যখন রেফারেন্স ভেরিয়েবল ঘোষণা করবেন তখন আপনাকে অবশ্যই এটি স্থাপন করতে হবে এবং আপনি পরে এটিকে পরিবর্তন করতে পারবেন না।
আপডেট: এখন যেহেতু আমি এটি সম্পর্কে আরও কিছু চিন্তা করি, সেখানে একটি গুরুত্বপূর্ণ পার্থক্য রয়েছে।
কোনও কনস্ট পয়েন্টারের লক্ষ্য তার ঠিকানা গ্রহণ এবং কনস্ট কাস্ট ব্যবহার করে প্রতিস্থাপন করা যেতে পারে।
কোনও রেফারেন্সের টার্গেট কোনওভাবেই ইউবির সংক্ষেপে প্রতিস্থাপন করা যাবে না।
এটি কম্পাইলারকে একটি রেফারেন্সে আরও অনুকূলকরণের অনুমতি দেওয়া উচিত do
T* const
আলাদা সিনট্যাকটিক চিনির সাথে বুঝতে পেরেছি (যা আপনার কোড থেকে * এবং প্রচুর পরিমাণে মুছে ফেলার জন্য ঘটে)।
int i; int const *pci = &i; /* implicit conv to const int* */ int *pi = const_cast<int*>(pci);
ঠিক আছে।
জনপ্রিয় মতামতের বিপরীতে, কোনও রেফারেন্স পাওয়া যায় যা NUL।
int * p = NULL;
int & r = *p;
r = 1; // crash! (if you're lucky)
মঞ্জুর, একটি রেফারেন্স সহ এটি করা খুব শক্ত - তবে আপনি যদি এটি পরিচালনা করেন তবে আপনি এটির চেষ্টা করার জন্য আপনার চুল ছিঁড়ে ফেলবেন। তথ্যসূত্রগুলি সি ++ তে অন্তর্নিহিত নিরাপদ নয় !
প্রযুক্তিগতভাবে এটি একটি অবৈধ রেফারেন্স , নাল রেফারেন্স নয়। সি ++ নাল রেফারেন্সকে ধারণা হিসাবে সমর্থন করে না কারণ আপনি অন্যান্য ভাষায় খুঁজে পেতে পারেন। এছাড়াও অন্যান্য ধরণের অবৈধ উল্লেখ রয়েছে। কোনও অবৈধ রেফারেন্স অপরিজ্ঞাত আচরণের ছাঁটাই উত্থাপন করে , ঠিক যেমন কোনও অবৈধ পয়েন্টার ব্যবহার করে।
প্রকৃত ত্রুটিটি কোনও রেফারেন্সের আগে বরাদ্দকরণের আগে NULL পয়েন্টারকে ডেরফেরিংয়ের মধ্যে রয়েছে। তবে আমি এমন কোনও সংকলক সম্পর্কে সচেতন নই যা এই শর্তে কোনও ত্রুটি তৈরি করবে - ত্রুটিটি কোডের পাশাপাশি আরও একটি পয়েন্টে প্রচার করে। এটাই এই সমস্যাটিকে এত কুখ্যাত করে তোলে। বেশিরভাগ সময়, আপনি যদি কোনও নল পয়েন্টারকে অবজ্ঞা করেন, আপনি ঠিক ঠিক সেই জায়গায় ক্র্যাশ হয়ে গিয়েছিলেন এবং এটি বের করতে খুব বেশি ডিবাগিং লাগে না।
আমার উপরের উদাহরণটি সংক্ষিপ্ত এবং স্বীকৃত। এখানে আরও একটি বাস্তব-বিশ্বের উদাহরণ।
class MyClass
{
...
virtual void DoSomething(int,int,int,int,int);
};
void Foo(const MyClass & bar)
{
...
bar.DoSomething(i1,i2,i3,i4,i5); // crash occurs here due to memory access violation - obvious why?
}
MyClass * GetInstance()
{
if (somecondition)
return NULL;
...
}
MyClass * p = GetInstance();
Foo(*p);
আমি আবারও বলতে চাই যে নাল রেফারেন্স পাওয়ার একমাত্র উপায় হ'ল ত্রুটিযুক্ত কোডের মাধ্যমে, এবং একবার আপনার এটি হয়ে গেলে আপনি সংজ্ঞায়িত আচরণ পাচ্ছেন। এটা তোলে কখনো একটি নাল রেফারেন্সের জন্য চেক করতে ইন্দ্রিয় তোলে; উদাহরণস্বরূপ আপনি চেষ্টা করতে পারেন if(&bar==NULL)...
তবে সংকলকটি অস্তিত্বের বাইরে থাকা বিবৃতিটিকে অনুকূল করতে পারে! একটি বৈধ রেফারেন্স কখনই নুল হতে পারে না তাই সংকলকের দর্শন থেকে তুলনাটি সর্বদা মিথ্যা এবং if
ডেড কোড হিসাবে ধারাটি নির্মূল করা বিনামূল্যে - এটি অপরিবর্তিত আচরণের মূল বিষয়।
সমস্যা থেকে দূরে থাকার উপযুক্ত উপায় হ'ল একটি রেফারেন্স তৈরি করার জন্য কোনও NUL পয়েন্টারকে অবজ্ঞা করা এড়ানো। এটি সম্পাদন করার জন্য এখানে একটি স্বয়ংক্রিয় উপায়।
template<typename T>
T& deref(T* p)
{
if (p == NULL)
throw std::invalid_argument(std::string("NULL reference"));
return *p;
}
MyClass * p = GetInstance();
Foo(deref(p));
আরও ভাল লেখার দক্ষতার সাথে কারও কাছ থেকে এই সমস্যাটি দেখার জন্য, জিম হিসলপ এবং হার্ব সটারের নাল রেফারেন্সগুলি দেখুন ।
নাল পয়েন্টারকে অবজ্ঞার বিপদের আরেকটি উদাহরণের জন্য দেখুন রেমন্ড চেনের অন্য প্ল্যাটফর্মে কোড পোর্ট করার সময় অপরিজ্ঞাত আচরণের প্রকাশ করা ।
আপনি সবচেয়ে গুরুত্বপূর্ণ অংশটি ভুলে গেছেন:
পয়েন্টার সহ ->
সদস্য অ্যাক্সেস রেফারেন্স ব্যবহারের সাথে সদস্য অ্যাক্সেস ব্যবহার করে.
foo.bar
হয় পরিষ্কারভাবে শ্রেয় foo->bar
একই ভাবে যে চ হয় পরিষ্কারভাবে শ্রেয় গিয়ে Emacs :-)
->
পয়েন্টারগুলিকে রেফারেন্স সরবরাহ করে ঠিক যেমন পয়েন্টার নিজেই।
.
এবং ->
vi এবং
.
করা ব্যবহারের চেয়ে ভাল ->
তবে ভি বনাম ইমাসের মতো এটি সম্পূর্ণরূপে বিষয়গত এবং আপনি কোনও কিছুই প্রমাণ করতে পারবেন না
রেফারেন্সগুলি পয়েন্টারগুলির সাথে খুব মিল, তবে তারা সংকলকগুলির অনুকূলকরণে সহায়ক হতে বিশেষভাবে তৈরি করা হয়।
উদাহরণ হিসাবে:
void maybeModify(int& x); // may modify x in some way
void hurtTheCompilersOptimizer(short size, int array[])
{
// This function is designed to do something particularly troublesome
// for optimizers. It will constantly call maybeModify on array[0] while
// adding array[1] to array[2]..array[size-1]. There's no real reason to
// do this, other than to demonstrate the power of references.
for (int i = 2; i < (int)size; i++) {
maybeModify(array[0]);
array[i] += array[1];
}
}
একটি অনুকূলকরণ সংকলক বুঝতে পারে যে আমরা একটি [0] এবং একটি [1] বেশ গুচ্ছ অ্যাক্সেস করছি। এটি এতে অ্যালগরিদমকে অনুকূল করতে পছন্দ করবে:
void hurtTheCompilersOptimizer(short size, int array[])
{
// Do the same thing as above, but instead of accessing array[1]
// all the time, access it once and store the result in a register,
// which is much faster to do arithmetic with.
register int a0 = a[0];
register int a1 = a[1]; // access a[1] once
for (int i = 2; i < (int)size; i++) {
maybeModify(a0); // Give maybeModify a reference to a register
array[i] += a1; // Use the saved register value over and over
}
a[0] = a0; // Store the modified a[0] back into the array
}
এই ধরনের একটি অপ্টিমাইজেশন করতে, এটি প্রমাণ করতে হবে যে কল করার সময় অ্যারে [1] কিছুই পরিবর্তন করতে পারে না। এটি করা বরং বরং সহজ। আমি কখনই 2 এর চেয়ে কম নয়, সুতরাং অ্যারে [i] কখনও অ্যারে [1] উল্লেখ করতে পারে না। হতে পারে মোডিফাই () কে রেফারেন্স হিসাবে aliasing দেওয়া হয় (aliasing অ্যারে [0])। কোনও "রেফারেন্স" পাটিগণিত না থাকায়, সংকলকটি কেবল প্রমাণ করতে হয়েছিল যে সম্ভবতমাডিফাই কখনও x এর ঠিকানা পায় না এবং এটি প্রমাণিত হয়েছে যে কিছুই অ্যারে পরিবর্তন করে না [1]
এটিও প্রমাণ করতে হবে যে ভবিষ্যতের কল একটি [পড়তে] / লিখতে পারে এমন কোনও উপায় নেই যখন আমাদের কাছে এটির অস্থায়ী রেজিস্টার কপি আছে0। এটি প্রায়শই প্রমাণ করার জন্য তুচ্ছ, কারণ অনেক ক্ষেত্রেই স্পষ্ট যে রেফারেন্সটি কোনও শ্রেণীর উদাহরণের মতো স্থায়ী কাঠামোতে কখনও সংরক্ষণ করা হয় না।
এখন পয়েন্টার দিয়ে একই জিনিস
void maybeModify(int* x); // May modify x in some way
void hurtTheCompilersOptimizer(short size, int array[])
{
// Same operation, only now with pointers, making the
// optimization trickier.
for (int i = 2; i < (int)size; i++) {
maybeModify(&(array[0]));
array[i] += array[1];
}
}
আচরণ একই; কেবলমাত্র এখন প্রমাণ করা অনেক কঠিন যে সম্ভবতমাডিফাই কখনও অ্যারে পরিবর্তন করে না [1], কারণ আমরা ইতিমধ্যে এটি একটি পয়েন্টার দিয়েছি; বিড়াল থলের মধ্য থেকে বের হয়. এখন এটি আরও জটিল প্রমাণ করতে হবে: এটি সম্ভবত & x + 1 তে কখনও লেখেন না তা প্রমাণ করার জন্য মডফাইফের একটি স্ট্যাটিক বিশ্লেষণ এটি প্রমাণ করতে হবে যে এটি অ্যারে [0] উল্লেখ করতে পারে এমন কোনও পয়েন্টারটি কখনও সংরক্ষণ করে না, যা ঠিক কৌতুকময়
আধুনিক সংকলক স্থিতিশীল বিশ্লেষণে আরও ভাল এবং উন্নত হচ্ছে তবে তাদের সাহায্য করার জন্য এবং উল্লেখগুলি ব্যবহার করার জন্য এটি সর্বদা দুর্দান্ত।
অবশ্যই, এই ধরনের চৌকস অপটিমাইজেশন বাদ দিয়ে, সংকলকগণ যখন প্রয়োজন হবে তখন অবশ্যই রেফারেন্সগুলিকে পয়েন্টারে পরিণত করবে।
সম্পাদনা: এই উত্তরটি পোস্ট করার পাঁচ বছর পরে, আমি একটি প্রকৃত প্রযুক্তিগত পার্থক্য পেয়েছি যেখানে রেফারেন্সগুলি একই সম্বোধন ধারণার দিকে তাকানোর কেবল ভিন্ন পদ্ধতির চেয়ে আলাদা। উল্লেখগুলি অস্থায়ী বস্তুর আজীবন এমনভাবে পরিবর্তন করতে পারে যা পয়েন্টারগুলি পারে না।
F createF(int argument);
void extending()
{
const F& ref = createF(5);
std::cout << ref.getArgument() << std::endl;
};
সাধারনত অস্থায়ী বস্তু যেমন কল দ্বারা তৈরি করা createF(5)
অভিব্যক্তিটির শেষে ধ্বংস হয়। তবে, সেই বস্তুকে রেফারেন্সের সাথে আবদ্ধ করে ref
, C ++ সেই অস্থায়ী অবজেক্টের আয়ু বাড়িয়ে দেবে যতক্ষণ না ref
সুযোগের বাইরে চলে যায়।
maybeModify
কোনও কিছুর ঠিকানা গ্রহণ করে না তা নির্ধারণ করা যে x
একগুচ্ছ পয়েন্টার গাণিতিক সংঘটিত হয় না তা প্রমাণ করার চেয়ে যথেষ্ট সহজ।
void maybeModify(int& x) { 1[&x]++; }
, যা উপরের অন্যান্য মন্তব্যগুলি আলোচনা করছে
আসলে, একটি রেফারেন্স আসলে পয়েন্টারের মতো নয়।
একটি সংকলক একটি পরিবর্তনকে "রেফারেন্স" রাখে, একটি নামকে মেমোরি ঠিকানার সাথে যুক্ত করে; সংকলনের সময় কোনও ভেরিয়েবলের নাম কোনও মেমরি ঠিকানায় অনুবাদ করা এটাই তার কাজ।
আপনি যখন কোনও রেফারেন্স তৈরি করেন, আপনি কেবলমাত্র সংকলককে বলে থাকেন যে আপনি পয়েন্টার ভেরিয়েবলের জন্য অন্য নাম নির্ধারণ করেছেন; সে কারণেই রেফারেন্সগুলি "নালকে নির্দেশ" করতে পারে না, কারণ একটি পরিবর্তনশীল হতে পারে না এবং হতে পারে না।
পয়েন্টারগুলি ভেরিয়েবল হয়; এগুলিতে কিছু অন্যান্য ভেরিয়েবলের ঠিকানা থাকে বা শূন্য হতে পারে। গুরুত্বপূর্ণ বিষয়টি হল যে কোনও পয়েন্টারের একটি মান থাকে তবে একটি রেফারেন্সের কেবলমাত্র একটি চলক থাকে যা এটি উল্লেখ করা হয়।
এখন বাস্তব কোড সম্পর্কে কিছু ব্যাখ্যা:
int a = 0;
int& b = a;
এখানে আপনি অন্য ভেরিয়েবল তৈরি করছেন না যা নির্দেশ করে a
; আপনি কেবল মানটির সাথে থাকা মেমরি সামগ্রীতে অন্য একটি নাম যুক্ত করছেন a
। এই মেমরি এখন দুটি নাম আছে, a
এবং b
, এবং এটা হয় নাম ব্যবহার করে সম্বোধন করা যেতে পারে।
void increment(int& n)
{
n = n + 1;
}
int a;
increment(a);
কোনও ফাংশন কল করার সময়, সংকলকটি সাধারণত আর্গুমেন্টে অনুলিপি করার জন্য মেমরি স্পেস তৈরি করে। ফাংশন স্বাক্ষরটি তৈরি করা উচিত ফাঁকা স্থানগুলি সংজ্ঞায়িত করে এবং এই স্থানগুলির জন্য ব্যবহার করা উচিত এমন নাম দেয়। একটি প্যারামিটারটিকে রেফারেন্স হিসাবে ঘোষণা করা সংস্থাপককে কেবল ইনপুট ভেরিয়েবল মেমরি স্পেসটি ব্যবহার করার পরিবর্তে পদ্ধতি কলের সময় নতুন মেমরির স্থান বরাদ্দ করার পরিবর্তে বলে। এটি অদ্ভুত বলে মনে হতে পারে যে আপনার ফাংশনটি কলিং স্কোপটিতে ঘোষিত কোনও পরিবর্তনশীলকে সরাসরি পরিচালনা করবে, তবে মনে রাখবেন যে সংকলিত কোডটি কার্যকর করার সময়, এর আর কোনও সুযোগ নেই; এখানে কেবল সমতল সমতল মেমরি রয়েছে এবং আপনার ফাংশন কোডটি কোনও ভেরিয়েবলকে ম্যানিপুলেট করতে পারে।
এখন কিছু ক্ষেত্রে থাকতে পারে যেখানে আপনার সংকলক বাহ্যিক ভেরিয়েবল ব্যবহার করার সময় সংকলন করার সময় রেফারেন্সটি জানতে নাও পারেন। সুতরাং একটি রেফারেন্স অন্তর্নিহিত কোডে পয়েন্টার হিসাবে প্রয়োগ করা যেতে পারে বা নাও হতে পারে। তবে আমি আপনাকে যে উদাহরণগুলি দিয়েছি, সম্ভবত এটি কোনও পয়েন্টার দিয়ে প্রয়োগ করা হবে না।
একটি রেফারেন্স কখনও হতে পারে NULL
।
void Foo::bar() { virtual_baz(); }
সেগফাল্টের মতো কোড থাকে । যদি আপনি সচেতন না হন যে উল্লেখগুলি নালাগুলি হতে পারে তবে আপনি শূন্যটিকে এর উত্সটিতে ফিরে পেতে পারবেন না।
int &r=*p;
হ'ল অপরিজ্ঞাত আচরণ। এই মুহুর্তে, আপনি একটি নেই "শূন্য রেফারেন্স ইশারা," যদি আপনি একটি প্রোগ্রাম আছে আর সম্পর্কে কারণগত যাবে এ সব ।
রেফারেন্স এবং পয়েন্টার উভয়ই অপ্রত্যক্ষভাবে অন্য মানটি অ্যাক্সেস করতে ব্যবহৃত হয়, তবে উল্লেখ এবং পয়েন্টারগুলির মধ্যে দুটি গুরুত্বপূর্ণ পার্থক্য রয়েছে। প্রথমটি হ'ল একটি রেফারেন্স সর্বদা একটি অবজেক্টকে বোঝায়: কোনও রেফারেন্স শুরু না করেই এটি সংজ্ঞা দেওয়া ত্রুটি। অ্যাসাইনমেন্টের আচরণটি দ্বিতীয় গুরুত্বপূর্ণ পার্থক্য: একটি রেফারেন্সকে বরাদ্দ করা বিষয়টিকে রেফারেন্সের সাথে আবদ্ধ করে দেয়; এটি অন্য কোনও অবজেক্টের রেফারেন্স পুনরায় ফিরিয়ে দেয় না। একবার শুরু হয়ে গেলে, একটি রেফারেন্স সর্বদা একই অন্তর্নিহিত বস্তুকে বোঝায়।
এই দুটি প্রোগ্রামের টুকরো বিবেচনা করুন। প্রথমটিতে, আমরা অন্যকে একটি পয়েন্টার বরাদ্দ করি:
int ival = 1024, ival2 = 2048;
int *pi = &ival, *pi2 = &ival2;
pi = pi2; // pi now points to ival2
অ্যাসাইনমেন্টের পরে, iv, পাই দ্বারা সম্বোধিত বস্তুটি অপরিবর্তিত রয়েছে। অ্যাসাইনমেন্টটি পাইয়ের মান পরিবর্তন করে, এটি অন্য কোনও বস্তুর দিকে নির্দেশ করে। এখন একটি অনুরূপ প্রোগ্রাম বিবেচনা করুন যা দুটি রেফারেন্স নির্ধারণ করে:
int &ri = ival, &ri2 = ival2;
ri = ri2; // assigns ival2 to ival
এই অ্যাসাইনমেন্টটি আইভেলকে পরিবর্তন করে, রি দ্বারা রেফারেন্স করা মান, এবং নিজেই রেফারেন্সটি নয়। অ্যাসাইনমেন্টের পরে, দুটি রেফারেন্স এখনও তাদের মূল বস্তুগুলিকে বোঝায় এবং objects বস্তুর মানও এখন একইরকম।
আপনি যদি কোনও বিমূর্ত বা এমনকি একাডেমিক ফ্যাশনে কম্পিউটারের ভাষা অধ্যয়নের সাথে পরিচিত না হন তবে একটি অর্থগত পার্থক্য রয়েছে es
সর্বোচ্চ স্তরে, রেফারেন্সগুলির ধারণাটি হ'ল তারা স্বচ্ছ "এলিয়াস"। আপনার কম্পিউটারটি তাদের কাজ করার জন্য কোনও ঠিকানা ব্যবহার করতে পারে, তবে আপনাকে এটি নিয়ে চিন্তিত হওয়ার কথা নয়: আপনি তাদের কোনও বিদ্যমান বস্তুর জন্য "কেবলমাত্র অন্য একটি নাম" হিসাবে ভাবেন এবং সিনট্যাক্সটি সেটিকে প্রতিফলিত করে। এগুলি পয়েন্টারের তুলনায় আরও কঠোর, যাতে আপনি যখন ঝোলা ঝুঁকিপূর্ণ পয়েন্টার তৈরি করতে যাবেন তার চেয়ে আপনার সংকলক আপনাকে আরও নির্ভরযোগ্যভাবে সতর্ক করতে পারে।
এর বাইরেও পয়েন্টার এবং রেফারেন্সের মধ্যে অবশ্যই কিছু ব্যবহারিক পার্থক্য রয়েছে। এগুলি ব্যবহারের বাক্য গঠনটি অবশ্যই স্পষ্টতই আলাদা এবং আপনি "পুনরায় আসন" রেফারেন্স করতে পারবেন না, বাছাইয়ের কোনও উল্লেখ রাখতে পারবেন না বা রেফারেন্সের পয়েন্টার রাখতে পারবেন না।
একটি রেফারেন্স অন্য ভেরিয়েবলের জন্য একটি উপাম যেখানে একটি পয়েন্টার একটি ভেরিয়েবলের মেমরি ঠিকানা রাখে। রেফারেন্সগুলি সাধারণত ফাংশন প্যারামিটার হিসাবে ব্যবহৃত হয় যাতে পাস করা বস্তুটি অনুলিপি নয় বরং নিজেই object
void fun(int &a, int &b); // A common usage of references.
int a = 0;
int &b = a; // b is an alias for a. Not so common to use.
এটি কতটা জায়গা নেয় তা বিবেচনাধীন নয় যেহেতু আপনি যে জায়গাতেই গ্রহণ করবেন তা বাস্তবে কোনও পার্শ্ব প্রতিক্রিয়া (কোড প্রয়োগ না করে) দেখতে পাচ্ছেন না।
অন্যদিকে, রেফারেন্স এবং পয়েন্টারগুলির মধ্যে একটি প্রধান পার্থক্য হ'ল কনস্টের রেফারেন্সকে সীমাবদ্ধ না করা পর্যন্ত কনস্টের রেফারেন্সগুলিকে অর্পণ করা টেম্পোরারিগুলি লাইভ থাকে।
উদাহরণ স্বরূপ:
class scope_test
{
public:
~scope_test() { printf("scope_test done!\n"); }
};
...
{
const scope_test &test= scope_test();
printf("in scope\n");
}
মুদ্রণ করবে:
in scope
scope_test done!
এটি সেই ভাষা পদ্ধতি যা স্কোপগার্ডকে কাজ করতে দেয়।
এটি টিউটোরিয়াল ভিত্তিক । যা লেখা আছে তা আরও স্পষ্ট করে তোলে:
>>> The address that locates a variable within memory is
what we call a reference to that variable. (5th paragraph at page 63)
>>> The variable that stores the reference to another
variable is what we call a pointer. (3rd paragraph at page 64)
কেবল এটি মনে রাখা,
>>> reference stands for memory location
>>> pointer is a reference container (Maybe because we will use it for
several times, it is better to remember that reference.)
আরও কী, আমরা প্রায় যে কোনও পয়েন্টার টিউটোরিয়ালটি উল্লেখ করতে পারি, পয়েন্টার হ'ল পয়েন্টার এমন একটি বস্তু যা পয়েন্টার পাটিগণিত দ্বারা সমর্থিত যা পয়েন্টারকে অ্যারের অনুরূপ করে তোলে।
নিম্নলিখিত বিবৃতি দেখুন,
int Tom(0);
int & alias_Tom = Tom;
alias_Tom
একটি হিসাবে বোঝা যায় alias of a variable
( typedef
যার সাথে পৃথক হয় alias of a type
) Tom
। এ জাতীয় বিবৃতিটির পরিভাষাটি একটি রেফারেন্স তৈরি করা ভুলে যাওয়াও ঠিক Tom
।
nullptr
? আপনি আসলে এই থ্রেডের অন্য কোনও অংশ পড়েছেন, বা ...?
একটি রেফারেন্স কিছু স্মৃতিতে দেওয়া অন্য নাম নয়। এটি একটি অপরিবর্তনীয় পয়েন্টার যা স্বয়ংক্রিয়ভাবে ব্যবহারে ডি-রেফারেন্সেড। মূলত এটি নিচে ফোটে:
int& j = i;
এটি অভ্যন্তরীণ হয়ে যায়
int* const j = &i;
const
পয়েন্টার বাস্তবায়নের জন্য একটি বৈধ উপায় । এই নমনীয়তা প্রমাণ করে না যে একটি রেফারেন্স এবং পয়েন্টারের মধ্যে পার্থক্য রয়েছে।
সি ++ এ একটি রেফারেন্স কী? টাইপের কিছু নির্দিষ্ট উদাহরণ যা কোনও অবজেক্ট টাইপ নয় ।
সি ++ এর পয়েন্টার কী? টাইপের কিছু নির্দিষ্ট উদাহরণ যা একটি অবজেক্ট টাইপ ।
থেকে অবজেক্টের তালিকায় আইএসও সি ++ সংজ্ঞা :
একটি অবজেক্ট টাইপ হ'ল (সম্ভবত সিভি- কোয়ালিফাইড) টাইপ যা কোনও ফাংশন টাইপ নয়, রেফারেন্স টাইপ নয়, সিভি অকার্যকর নয়।
এটি জেনে রাখা জরুরী হতে পারে, অবজেক্ট টাইপ হ'ল সি ++ তে মহাবিশ্বের ধরণের একটি শীর্ষ স্তরের বিভাগ। রেফারেন্সটিও একটি শীর্ষ স্তরের বিভাগ। তবে পয়েন্টারটি হয় না।
যৌগিক ধরণের প্রসঙ্গে পয়েন্টার এবং রেফারেন্সগুলি একসাথে উল্লেখ করা হয়েছে । এটি মূলত (এবং প্রসারিত) সি থেকে উত্তরাধিকার সূত্রে প্রাপ্ত ঘোষক সিনট্যাক্সের প্রকৃতির কারণে, যার কোনও উল্লেখ নেই। (তদ্ব্যতীত, সি ++ ১১ এর পরে একাধিক ধরণের রেফারেন্সার রয়েছে, যদিও পয়েন্টারগুলি এখনও "unityক্যবদ্ধ": &
+ &&
বনাম *
।) সুতরাং এই প্রসঙ্গে সি এর অনুরূপ শৈলীর সাথে "এক্সটেনশন" দ্বারা নির্দিষ্ট একটি ভাষা খসড়া কিছুটা যুক্তিসঙ্গত । (আমি এখনও তর্ক করব যে ঘোষকগণের বাক্য গঠন সিনট্যাক্টিক ভাব প্রকাশকে প্রচুর অপচয় করে , মানব ব্যবহারকারী এবং বাস্তবায়ন উভয়ই হতাশ করে তোলে Thus সুতরাং, এগুলি সমস্তই অন্তর্নির্মিত হওয়ার যোগ্য নয়)একটি নতুন ভাষা নকশা। এটি পিএল ডিজাইন সম্পর্কে সম্পূর্ণ ভিন্ন বিষয়, যদিও))
অন্যথায়, এটি নগণ্য যে পয়েন্টারগুলি একসাথে রেফারেন্স সহ নির্দিষ্ট ধরণের ধরণের হিসাবে যোগ্য হতে পারে। এগুলি সিনট্যাক্সের মিলের পাশাপাশি খুব কম সাধারণ বৈশিষ্ট্যগুলি ভাগ করে, তাই বেশিরভাগ ক্ষেত্রে এগুলি একত্রে রাখার দরকার নেই।
উপরের বিবৃতিগুলিতে কেবল "পয়েন্টার" এবং "রেফারেন্স" প্রকার হিসাবে উল্লেখ করুন নোট করুন। তাদের দৃষ্টান্তগুলি সম্পর্কে কিছু আগ্রহী প্রশ্ন রয়েছে (যেমন ভেরিয়েবল)। অনেকগুলি ভুল ধারণাও আসে।
শীর্ষ-স্তরের বিভাগগুলির পার্থক্য ইতিমধ্যে অনেকগুলি কংক্রিটের পার্থক্য প্রকাশ করতে পারে যেগুলি সরাসরি পয়েন্টারগুলিতে আবদ্ধ নয়:
cv
যোগ্যতা থাকতে পারে। তথ্যসূত্রগুলি পারে না।তথ্যসূত্র সম্পর্কে আরও কয়েকটি বিশেষ বিধি:
&&
টেমপ্লেট প্যারামিটার ছাড়ের সময় রেফারেন্স ভেঙে যাওয়ার ভিত্তিতে প্যারামিটারগুলিতে ("ফরওয়ার্ডিং রেফারেন্স হিসাবে") বিশেষ নিয়মগুলি পরামিতিগুলির "নিখুঁত ফরোয়ার্ডিং" এর অনুমতি দেয় ।std::initializer_list
রেফারেন্স আজীবন সম্প্রসারণের অনুরূপ কিছু নিয়ম অনুসরণ করে। এটি কৃমি আরেকটি ক্যান।আমি জানি রেফারেন্সগুলি সিনট্যাকটিক চিনি, তাই কোড পড়া এবং লেখা সহজ।
প্রযুক্তিগতভাবে, এটি সাধারণ ভুল। রেফারেন্সগুলি সি ++ তে অন্য কোনও বৈশিষ্ট্যের সিনট্যাকটিক চিনির নয়, কারণ সেগুলি কোনও সিন্থেটিক পার্থক্য ছাড়াই অন্য বৈশিষ্ট্যগুলি দ্বারা ঠিক প্রতিস্থাপন করা যায় না।
(একইভাবে, ল্যাম্বডা-এক্সপ্রেশন গুলি সি ++ তে অন্য কোনও বৈশিষ্ট্যের সিনট্যাকটিক চিনি নয় কারণ এটি "অনির্দিষ্ট" বৈশিষ্ট্যগুলির সাথে ক্যাপচারড ভেরিয়েবলগুলির ডিক্লেয়ারেশন অর্ডের মতো সুনির্দিষ্টভাবে অনুকরণ করা যায় না , যা গুরুত্বপূর্ণ হতে পারে কারণ এ জাতীয় ভেরিয়েবলগুলির আরম্ভের ক্রম হতে পারে) উল্লেখযোগ্য।)
এই কঠোর অর্থে সি ++ এর কয়েক ধরণের সিনট্যাকটিক সুগার রয়েছে। একটি উদাহরণ হ'ল (সি থেকে উত্তরাধিকার সূত্রে প্রাপ্ত) বিল্ট-ইন (অ-ওভারলোডেড) অপারেটর []
, যা বিল্ট-ইন অপারেটর অ্যানারি *
এবং বাইনারিগুলির উপর নির্দিষ্ট ফর্মের সংমিশ্রণের একই শব্দার্থক বৈশিষ্ট্যগুলি সংজ্ঞায়িত করা হয়েছে+
।
সুতরাং, একটি পয়েন্টার এবং একটি রেফারেন্স উভয় একই পরিমাণে মেমরি ব্যবহার করে।
উপরের বিবৃতিটি কেবল ভুল। এই ধরনের ভুল ধারণা এড়াতে, পরিবর্তে আইএসও সি ++ বিধিগুলি দেখুন:
থেকে [intro.object] / 1 :
... একটি অবজেক্ট তার নির্মাণকালের পুরো সময়কালে এবং তার ধ্বংসের সময়কালে স্টোরেজের একটি অঞ্চল দখল করে। ...
থেকে [dcl.ref] / 4 :
কোনও রেফারেন্সের স্টোরেজ প্রয়োজন কিনা তা অনির্দিষ্ট।
এগুলি অর্থপূর্ণ বৈশিষ্ট্যগুলি নোট করুন ।
এমনকি পয়েন্টারগুলি ভাষা নকশার বিবেচনায় রেফারেন্সের সাথে একত্রে রাখার মতো পর্যাপ্ত যোগ্য নয়, এখনও কিছু যুক্তি রয়েছে যা কিছু অন্যান্য প্রসঙ্গে তাদের মধ্যে নির্বাচন করা বিতর্কযোগ্য করে তোলে, উদাহরণস্বরূপ, প্যারামিটারের ধরণের ক্ষেত্রে পছন্দগুলি করার সময়।
তবে এটি পুরো গল্প নয়। আমি বলতে চাইছি, পয়েন্টার বনাম রেফারেন্সের তুলনায় আপনার আরও অনেকগুলি বিষয় রয়েছে consider
আপনি এই ধরনের ওভার নির্দিষ্ট পছন্দের উপর বিদ্ধ না থাকে তাহলে বেশিরভাগ ক্ষেত্রেই উত্তর খুব বেশী নেই আপনি ব্যবহার পয়েন্টার প্রয়োজনীয়তা থাকে না, তাই আপনি না । পয়েন্টারগুলি সাধারণত যথেষ্ট খারাপ হয় কারণ এগুলি আপনার প্রত্যাশা করে না এমন অনেকগুলি বিষয়কে বোঝায় এবং তারা কোডের রক্ষণাবেক্ষণযোগ্যতা এবং এমনকি (এমনকি) বহনযোগ্যতাকে ক্ষুন্ন করে এমন অনেকগুলি অন্তর্নিহিত অনুমানের উপর নির্ভর করবে। অযথা পয়েন্টারগুলির উপর নির্ভর করা অবশ্যই একটি খারাপ শৈলী এবং এটি আধুনিক সি ++ অর্থে এড়ানো উচিত। আপনার উদ্দেশ্যটি নিয়ে পুনর্বিবেচনা করুন এবং অবশেষে আপনি দেখতে পাবেন যে পয়েন্টারটি বেশিরভাগ ক্ষেত্রে সর্বশেষের বৈশিষ্ট্য ।
&
রেফারেন্সের ধরণের প্রয়োজন। (এবং সাধারণত এটি const
যোগ্যতা অর্জন করা উচিত ।)&&
রেফারেন্স টাইপ প্রয়োজন require (এবং সাধারণত কোনও বাছাইকারী হওয়া উচিত নয়))operator=
বিশেষ সদস্য ফাংশন হিসাবে ওভারলোডডের জন্য অনুলিপি / মুভ কনস্ট্রাক্টরের 1 ম প্যারামিটারের অনুরূপ রেফারেন্স প্রকারের প্রয়োজন হয়।++
ডামি দরকার int
।unique_ptr
এবং shared_ptr
(বা এমনকি যদি হোমব্রিউগুলির সাথে যদি আপনার অস্বচ্ছ প্রয়োজন হয় তবে ) ব্যবহার করুন।std::optional
, তবে কাঁচা পয়েন্টারগুলির পরিবর্তে মোড়কের মতো ব্যবহার করুন ।observer_ptr
লাইব্রেরি ফান্ডামেন্টাল টিএস এর মতো প্রায়শই আরও উপযুক্ত কিছু থাকে ।কেবলমাত্র ব্যতিক্রমগুলি বর্তমান ভাষায় কাজ করা যায় না:
operator new
। (তবে, সিভি - void*
সাধারণ অবজেক্ট পয়েন্টারগুলির তুলনায় এখনও বেশ আলাদা এবং সুরক্ষিত কারণ এটি অপ্রত্যাশিত পয়েন্টার পাটিগণিতকে বাতিল করে দেয় যদি না আপনি জিএনইউর মতো কিছু অবিস্মরণীয় এক্সটেনশানের উপর নির্ভর না করেন void*
।)সুতরাং, বাস্তবে, উত্তরটি এতটাই সুস্পষ্ট: সন্দেহ হলে, পয়েন্টারগুলি এড়িয়ে যান । আপনাকে কেবলমাত্র পয়েন্টার ব্যবহার করতে হবে যখন খুব স্পষ্ট কারণ রয়েছে যে অন্য কোনও কিছুই উপযুক্ত নয়। উপরে উল্লিখিত কয়েকটি ব্যতিক্রমী মামলা ব্যতীত, এই জাতীয় পছন্দগুলি প্রায়শই নিখুঁতভাবে সি ++ - সুনির্দিষ্ট হয় না (তবে সম্ভবত ভাষা-প্রয়োগকরণ-নির্দিষ্ট হতে পারে)। যেমন উদাহরণগুলি হতে পারে:
যদি আপনি কিছু গুগল অনুসন্ধান ফলাফলের মাধ্যমে প্রশ্নটি দেখতে পান (সি ++ এর সাথে সুনির্দিষ্ট নয়) তবে এটি খুব সম্ভবত ভুল জায়গা হতে পারে।
সি ++ এর রেফারেন্সগুলি বেশ "বিজোড়", কারণ এটি মূলত প্রথম-শ্রেণীর নয়: তাদেরকে বস্তু বা ফাংশনগুলি হিসাবে উল্লেখ করা হবে হিসাবে বিবেচনা করা হবে যাতে তারা কিছু প্রথম-শ্রেণীর ক্রিয়াকলাপকে যেমন বাম অপারেন্ড হিসাবে সমর্থন করার সুযোগ না পায় সদস্য অ্যাক্সেস অপারেটর রেফারেন্স করা অবজেক্টের ধরণে স্বাধীনভাবে ly অন্যান্য ভাষাগুলিতে তাদের উল্লেখগুলিতে একই রকম বাধা থাকতে পারে বা নাও থাকতে পারে।
সি ++ তে উল্লেখগুলি সম্ভবত বিভিন্ন ভাষায় অর্থ সংরক্ষণ করবে না। উদাহরণস্বরূপ, সাধারণভাবে রেফারেন্সগুলি সি ++ এর মতো মূল্যবোধগুলিতে অযৌক্তিক বৈশিষ্ট্য বোঝায় না, সুতরাং এই ধরনের অনুমানগুলি অন্য কয়েকটি ভাষায় কাজ নাও করতে পারে (এবং আপনি জবাব, সি #, ...) খুব সহজেই পাল্টা উদাহরণগুলি খুঁজে পাবেন।
সাধারণভাবে বিভিন্ন প্রোগ্রামিং ভাষাগুলির রেফারেন্সগুলির মধ্যে এখনও কিছু সাধারণ বৈশিষ্ট্য থাকতে পারে তবে এসও-তে কিছু অন্যান্য প্রশ্নের জন্য এটি ছেড়ে দেওয়া যাক।
(একটি পক্ষের নোট: ALGOL 68 বনাম পিএল / আই এর মতো যে কোনও "সি-জাতীয়" ভাষা জড়িত রয়েছে তার চেয়ে আগে প্রশ্নটি উল্লেখযোগ্য হতে পারে ))
সি ++ তে পয়েন্টারের একটি রেফারেন্স সম্ভব, তবে বিপরীতটি সম্ভব নয় মানে একটি রেফারেন্সের পয়েন্টার দেওয়া সম্ভব নয়। পয়েন্টারের একটি রেফারেন্স পয়েন্টারটি সংশোধন করতে একটি ক্লিনার সিনট্যাক্স সরবরাহ করে। এই উদাহরণটি দেখুন:
#include<iostream>
using namespace std;
void swap(char * &str1, char * &str2)
{
char *temp = str1;
str1 = str2;
str2 = temp;
}
int main()
{
char *str1 = "Hi";
char *str2 = "Hello";
swap(str1, str2);
cout<<"str1 is "<<str1<<endl;
cout<<"str2 is "<<str2<<endl;
return 0;
}
এবং উপরের প্রোগ্রামটির সি সংস্করণটি বিবেচনা করুন। সিতে আপনাকে পয়েন্টার থেকে পয়েন্টার (একাধিক দিকনির্দেশ) ব্যবহার করতে হবে এবং এটি বিভ্রান্তির দিকে নিয়ে যায় এবং প্রোগ্রামটি জটিল দেখায়।
#include<stdio.h>
/* Swaps strings by swapping pointers */
void swap1(char **str1_ptr, char **str2_ptr)
{
char *temp = *str1_ptr;
*str1_ptr = *str2_ptr;
*str2_ptr = temp;
}
int main()
{
char *str1 = "Hi";
char *str2 = "Hello";
swap1(&str1, &str2);
printf("str1 is %s, str2 is %s", str1, str2);
return 0;
}
পয়েন্টারের রেফারেন্স সম্পর্কে আরও তথ্যের জন্য নিম্নলিখিতটি দেখুন:
আমি যেমন বলেছি, একটি রেফারেন্সের পয়েন্টার সম্ভব নয়। নিম্নলিখিত প্রোগ্রাম চেষ্টা করুন:
#include <iostream>
using namespace std;
int main()
{
int x = 10;
int *ptr = &x;
int &*ptr1 = ptr;
}
আমার এইগুলির কোনওটির প্রয়োজন না হলে আমি রেফারেন্স ব্যবহার করি:
নাল পয়েন্টারগুলি সেন্ডিনেল মান হিসাবে ব্যবহার করা যেতে পারে, প্রায়শই ফাংশন ওভারলোডিং বা বুলের ব্যবহার এড়ানোর জন্য একটি সস্তা উপায়।
আপনি একটি পয়েন্টারে গাণিতিক করতে পারেন। উদাহরণ স্বরূপ,p += offset;
&r + offset
যেখানে আপনি লিখতে পারেনr
পয়েন্টার এবং রেফারেন্সের মধ্যে একটি মৌলিক পার্থক্য রয়েছে যা আমি কারও উল্লেখ করে দেখিনি: উল্লেখগুলি ফাংশন আর্গুমেন্টগুলিতে পাস-রেফারেন্স শব্দার্থকে সক্ষম করে enable পয়েন্টারগুলি, যদিও এটি প্রথমে দৃশ্যমান নয় তা নয়: তারা কেবল পাস-বাই-ভ্যালু শব্দার্থবিদ্যা সরবরাহ করে। এটি এই নিবন্ধে খুব সুন্দরভাবে বর্ণনা করা হয়েছে ।
শুভেচ্ছা, & rzej
বিভ্রান্তি যুক্ত হওয়ার ঝুঁকিতে, আমি কিছু ইনপুট ফেলতে চাই, আমি নিশ্চিত যে এটি প্রায়শই সংকলকটি রেফারেন্সগুলি কীভাবে প্রয়োগ করে তার উপর নির্ভর করে তবে জিসিসির ক্ষেত্রে এই ধারণাটি যে কোনও রেফারেন্স কেবল স্ট্যাকের একটি পরিবর্তনশীলকে নির্দেশ করতে পারে আসলে সঠিক নয়, উদাহরণস্বরূপ এটি নিন:
#include <iostream>
int main(int argc, char** argv) {
// Create a string on the heap
std::string *str_ptr = new std::string("THIS IS A STRING");
// Dereference the string on the heap, and assign it to the reference
std::string &str_ref = *str_ptr;
// Not even a compiler warning! At least with gcc
// Now lets try to print it's value!
std::cout << str_ref << std::endl;
// It works! Now lets print and compare actual memory addresses
std::cout << str_ptr << " : " << &str_ref << std::endl;
// Exactly the same, now remember to free the memory on the heap
delete str_ptr;
}
যার ফলে:
THIS IS A STRING
0xbb2070 : 0xbb2070
যদি আপনি খেয়াল করেন এমনকি মেমরিের ঠিকানাগুলিও ঠিক একইরকম হয়, যার অর্থ রেফারেন্সটি সাফল্যের সাথে হিপটিতে একটি পরিবর্তনশীলকে নির্দেশ করছে! এখন আপনি যদি সত্যিই অদ্ভুত হতে চান তবে এটিও কাজ করে:
int main(int argc, char** argv) {
// In the actual new declaration let immediately de-reference and assign it to the reference
std::string &str_ref = *(new std::string("THIS IS A STRING"));
// Once again, it works! (at least in gcc)
std::cout << str_ref;
// Once again it prints fine, however we have no pointer to the heap allocation, right? So how do we free the space we just ignorantly created?
delete &str_ref;
/*And, it works, because we are taking the memory address that the reference is
storing, and deleting it, which is all a pointer is doing, just we have to specify
the address with '&' whereas a pointer does that implicitly, this is sort of like
calling delete &(*str_ptr); (which also compiles and runs fine).*/
}
যার ফলে:
THIS IS A STRING
সুতরাং একটি রেফারেন্স হুডের নীচে একটি পয়েন্টার, তারা দুজনেই কেবল একটি মেমরি ঠিকানা সঞ্চয় করে চলেছে, যেখানে ঠিকানাটি নির্দেশ করছে অপ্রাসঙ্গিক, আমি কী বলেছি যদি std :: cout << str_ref; কলিংয়ের পরে & str_ref মুছবেন? ঠিক আছে, স্পষ্টতই এটি সূক্ষ্ম সংকলন করে, তবে রানটাইমের সময় সেগমেন্টেশন ত্রুটি সৃষ্টি করে কারণ এটি আর বৈধ ভেরিয়েবলটির দিকে ইশারা করে না, আমাদের মূলত একটি ভাঙা রেফারেন্স রয়েছে যা এখনও বিদ্যমান (এটি সুযোগ থেকে বেরিয়ে আসা অবধি), কিন্তু অকেজো।
অন্য কথায়, একটি রেফারেন্স কেবল পয়েন্টার ছাড়া কিছুই নয় যা পয়েন্টার মেকানিক্সকে দূরে সরিয়ে দেয়, এটি নিরাপদ এবং ব্যবহার করা সহজ করে তোলে (কোনও দুর্ঘটনাজনিত পয়েন্টার ম্যাথ, কোনও মিশ্রণ নেই '।' এবং '->' ইত্যাদি) আপনাকে ধরে নিয়েছে ing উপরে আমার উদাহরণগুলির মতো কোনও বাজে কথা চেষ্টা করবেন না;)
এখন নির্বিশেষে কিভাবে কম্পাইলার হ্যান্ডলগুলি রেফারেন্স, এটা হবে সবসময় ফণা অধীন পয়েন্টার কিছু আছে, কারণ একটি রেফারেন্স আবশ্যক কাজ প্রত্যাশিত হিসাবে এটির জন্য একটি নির্দিষ্ট মেমরি অ্যাড্রেস একটি নির্দিষ্ট পরিবর্তনশীল পড়ুন, কোন এই সমস্যা এড়ানোর পেয়ে (অত: পর হয় শব্দ 'রেফারেন্স')।
রেফারেন্স সহ মনে রাখা একমাত্র প্রধান নিয়মটি হ'ল ঘোষণার সময় এগুলি সংজ্ঞায়িত করতে হবে (একটি শিরোনামের রেফারেন্স ব্যতীত, অবশ্যই এটি কনস্ট্রাক্টরে সংজ্ঞায়িত করা উচিত, অবজেক্টের মধ্যে এটি অন্তর্ভুক্ত থাকার পরে) এটি নির্ধারণ করতে খুব দেরি হয়েছে)।
মনে রাখবেন, আমার উপরোক্ত উদাহরণগুলি কেবল এটিই, উদাহরণগুলি বোঝায় যে একটি রেফারেন্স কী, আপনি কখনই সেই উপায়ে কোনও রেফারেন্স ব্যবহার করতে চাইবেন না! একটি রেফারেন্সের সঠিক ব্যবহারের জন্য এখানে ইতিমধ্যে প্রচুর উত্তর রয়েছে যা মাথার পেরেকটি মারে
আরেকটি পার্থক্য হ'ল আপনার একটি শূন্য প্রকারের পয়েন্টার থাকতে পারে (এবং এর অর্থ কোনও কিছুর প্রতি নির্দেশক) তবে শূন্যতার উল্লেখগুলি নিষিদ্ধ।
int a;
void * p = &a; // ok
void & p = a; // forbidden
আমি বলতে পারি না যে আমি এই বিশেষ পার্থক্যে সত্যই খুশি। আমি অনেক পছন্দ করি যে এটি কোনও ঠিকানা সহ যে কোনও বিষয়ে অর্থের রেফারেন্স এবং অন্যথায় রেফারেন্সের জন্য একই আচরণের অনুমতি দেওয়া হবে। এটি সি লাইব্রেরির ফাংশনগুলির সমপরিমাণকে যেমন রেফারেন্সগুলি ব্যবহার করে মেমকিপির সংজ্ঞা দেয়।
এছাড়াও, একটি সূত্র যা কোনও ফাংশনের প্যারামিটার যা ইনলাইন করা থাকে তা পয়েন্টারের চেয়ে আলাদাভাবে পরিচালনা করা যেতে পারে।
void increment(int *ptrint) { (*ptrint)++; }
void increment(int &refint) { refint++; }
void incptrtest()
{
int testptr=0;
increment(&testptr);
}
void increftest()
{
int testref=0;
increment(testref);
}
পয়েন্টার সংস্করণটি ইনলাইন করার সময় অনেক সংকলক প্রকৃতপক্ষে মেমোরিতে একটি লিখনকে বাধ্য করে (আমরা স্পষ্টভাবে ঠিকানাটি নিচ্ছি)। তবে তারা রেজিস্ট্রারে রেজিস্ট্রেশনটি ছেড়ে দেবে যা আরও অনুকূল।
অবশ্যই, ফাংশনগুলির জন্য যা পয়েন্টার এবং রেফারেন্সের সাথে একই কোড তৈরি করে না এবং যদি ফাংশনটি পরিবর্তিত না করে এবং ফেরত না দেওয়া হয় তবে রেফারেন্সের চেয়ে মান অনুসারে আন্তঃনীতিগুলি উত্তীর্ণ করা ভাল।
উল্লেখগুলির আরেকটি আকর্ষণীয় ব্যবহার হ'ল কোনও ব্যবহারকারী-সংজ্ঞায়িত ধরণের ডিফল্ট যুক্তি সরবরাহ করা:
class UDT
{
public:
UDT() : val_d(33) {};
UDT(int val) : val_d(val) {};
virtual ~UDT() {};
private:
int val_d;
};
class UDT_Derived : public UDT
{
public:
UDT_Derived() : UDT() {};
virtual ~UDT_Derived() {};
};
class Behavior
{
public:
Behavior(
const UDT &udt = UDT()
) {};
};
int main()
{
Behavior b; // take default
UDT u(88);
Behavior c(u);
UDT_Derived ud;
Behavior d(ud);
return 1;
}
ডিফল্ট স্বাদ রেফারেন্সের 'অস্থায়ী থেকে বাইন্ড কনস্ট রেফারেন্স' ব্যবহার করে।
এই প্রোগ্রামটি প্রশ্নের উত্তর বুঝতে সাহায্য করতে পারে। এটি একটি রেফারেন্স "জে" এর একটি সাধারণ প্রোগ্রাম এবং একটি পয়েন্টার "পিটিআর" ভেরিয়েবল "এক্স" এর দিকে নির্দেশ করে।
#include<iostream>
using namespace std;
int main()
{
int *ptr=0, x=9; // pointer and variable declaration
ptr=&x; // pointer to variable "x"
int & j=x; // reference declaration; reference to variable "x"
cout << "x=" << x << endl;
cout << "&x=" << &x << endl;
cout << "j=" << j << endl;
cout << "&j=" << &j << endl;
cout << "*ptr=" << *ptr << endl;
cout << "ptr=" << ptr << endl;
cout << "&ptr=" << &ptr << endl;
getch();
}
প্রোগ্রামটি চালান এবং আউটপুটটি একবার দেখুন এবং আপনি বুঝতে পারবেন।
এছাড়াও, 10 মিনিট অতিরিক্ত রাখুন এবং এই ভিডিওটি দেখুন: https://www.youtube.com/watch?v=rlJrrGV0iOg
আমার মনে হচ্ছে এখানে আরও একটি বিষয় রয়েছে যা এখানে coveredাকা হয়নি।
পয়েন্টারগুলির বিপরীতে, রেফারেন্সগুলি সিন্টেক্সটিকভাবে তারা যে বস্তুটি উল্লেখ করে তার সমতুল্য , অর্থাত্ কোনও বস্তু প্রয়োগ করা যেতে পারে এমন কোনও ক্রিয়াকলাপ একটি রেফারেন্সের জন্য কাজ করে, এবং ঠিক একই বাক্য গঠন সহ (ব্যতিক্রমটি অবশ্যই আরম্ভ হয়)।
যদিও এটি পর্যায়ে প্রদর্শিত হতে পারে, আমি বিশ্বাস করি যে এই সম্পত্তিটি বেশ কয়েকটি সি ++ বৈশিষ্ট্যের জন্য অত্যন্ত গুরুত্বপূর্ণ, উদাহরণস্বরূপ:
টেম্পলেট । যেহেতু টেম্পলেট প্যারামিটারগুলি হাঁস-টাইপযুক্ত, তাই কোনও প্রকারের সিনট্যাকটিক বৈশিষ্ট্যগুলি গুরুত্বপূর্ণ, তাই প্রায়শই একই টেমপ্লেট T
এবং উভয়ই ব্যবহার করা যেতে পারে T&
।
(বা std::reference_wrapper<T>
যা এখনও কোনও অন্তর্নিহিত কাস্টের উপর নির্ভর করে T&
)
টেম্পলেটগুলি যা উভয়ই কভার করে T&
এবং T&&
আরও সাধারণ।
লভ্যালু । str[0] = 'X';
উল্লেখ ছাড়াই বিবৃতিটি বিবেচনা করুন এটি কেবল সি-স্ট্রিং ( char* str
) এর জন্য কাজ করবে । রেফারেন্স দ্বারা চরিত্রটি ফিরিয়ে দেওয়া ব্যবহারকারী-সংজ্ঞায়িত শ্রেণিগুলিকে একই স্বরলিপি রাখতে দেয়।
অনুলিপি নির্মাণকারী । সিন্ট্যাক্টিক্যালি এটি কনস্ট্রাক্টরদের অনুলিপি করার জন্য বস্তুগুলি পাস করার জন্য অর্থবোধ করে, এবং অবজেক্টগুলিতে পয়েন্টার না করে। তবে কোনও অনুলিপি নির্মাণকারীর পক্ষে মান অনুসারে কোনও জিনিস তোলার কোনও উপায় নেই - এর ফলে একই অনুলিপি নির্মাণকারীকে পুনরাবৃত্ত কল আসতে পারে। এটি এখানে একমাত্র বিকল্প হিসাবে রেফারেন্স দেয়।
অপারেটর ওভারলোডস । রেফারেন্স সহ অপারেটর কলের সাথে ইন্ডিয়ারেশন পরিচয় করানো সম্ভব - operator+(const T& a, const T& b)
একই ইনফিক্স নোটেশনটি ধরে রাখার সময় বলুন । এটি নিয়মিত ওভারলোডেড ফাংশনগুলির জন্যও কাজ করে।
এই পয়েন্টগুলি সি ++ এবং স্ট্যান্ডার্ড লাইব্রেরির একটি উল্লেখযোগ্য অংশকে ক্ষমতা দেয় যাতে এটি উল্লেখের বেশিরভাগ সম্পত্তি।
পয়েন্টার এবং রেফারেন্সগুলির মধ্যে একটি খুব গুরুত্বপূর্ণ অ-প্রযুক্তিগত পার্থক্য রয়েছে: পয়েন্টার দ্বারা একটি ফাংশনে প্রেরিত একটি আর্গুমেন্ট নন-কনস্ট্যান্ট রেফারেন্স দ্বারা কোনও ফাংশনে প্রেরিত আর্গুমেন্টের চেয়ে অনেক বেশি দৃশ্যমান। উদাহরণ স্বরূপ:
void fn1(std::string s);
void fn2(const std::string& s);
void fn3(std::string& s);
void fn4(std::string* s);
void bar() {
std::string x;
fn1(x); // Cannot modify x
fn2(x); // Cannot modify x (without const_cast)
fn3(x); // CAN modify x!
fn4(&x); // Can modify x (but is obvious about it)
}
ফিরে ইন সি, এমন কল যা দেখে মনে হয় fn(x)
কেবলমাত্র মান দ্বারা পাস করা যায়, তাই এটি অবশ্যই সংশোধন করতে পারে না x
; যুক্তি সংশোধন করতে আপনাকে পয়েন্টারটি পাস করতে হবে fn(&x)
। সুতরাং যদি কোনও যুক্তির আগে কোনও যুক্তি না আগে &
আপনি জানতেন এটি সংশোধন করা হবে না। (কথোপকথন, &
পরিবর্তিত অর্থ সত্য নয় কারণ আপনাকে কখনও কখনও const
পয়েন্টার দ্বারা বড় পঠনযোগ্য কেবল কাঠামো পাস করতে হবে would )
কিছু যুক্তি দেখান যে কোড পড়ার সময় এটি এমন দরকারী বৈশিষ্ট্য, সেই পয়েন্টার প্যারামিটারগুলি সর্বদা অ-পরিবর্তিত পরিবর্তনের পরিবর্তিত পরামিতিগুলির জন্য ব্যবহার করা উচিতconst
রেফারেন্সগুলির , এমনকি যদি ফাংশনটি কখনই প্রত্যাশা করে না nullptr
। অর্থাত, এই লোকেরা যুক্তি দেয় যে fn3()
উপরের মতো ফাংশন স্বাক্ষরগুলির অনুমতি দেওয়া উচিত নয়। গুগলের সি ++ স্টাইলের গাইডলাইনগুলি এর উদাহরণ।
একটি পয়েন্টার 0 এ আরম্ভ করা যেতে পারে এবং একটি রেফারেন্স নয়। আসলে, কোনও রেফারেন্স অবশ্যই কোনও অবজেক্টকে উল্লেখ করতে পারে তবে পয়েন্টারটি নাল পয়েন্টার হতে পারে:
int* p = 0;
কিন্তু আমরা থাকতে পারে না int& p = 0;
এবং int& p=5 ;
।
এটি যথাযথভাবে করার জন্য, আমরা অবশ্যই প্রথমে কোনও বিষয় ঘোষিত ও সংজ্ঞায়িত করেছি অবশ্যই আমরা সেই বস্তুর একটি রেফারেন্স তৈরি করতে পারি, সুতরাং পূর্ববর্তী কোডটির সঠিক প্রয়োগটি হবে:
Int x = 0;
Int y = 5;
Int& p = x;
Int& p1 = y;
আর একটি গুরুত্বপূর্ণ বিষয় হ'ল আমরা সূচনা ছাড়াই পয়েন্টার ঘোষণা করতে পারি তবে রেফারেন্সের ক্ষেত্রে এ জাতীয় কোনও কাজ করা যায় না যা অবশ্যই পরিবর্তনশীল বা বস্তুর প্রতি সর্বদা একটি রেফারেন্স তৈরি করতে হবে। তবে পয়েন্টারের এ জাতীয় ব্যবহার ঝুঁকিপূর্ণ তাই সাধারণভাবে আমরা পরীক্ষা করে দেখি যে পয়েন্টারটি আসলে কোনও দিকে ইশারা দিচ্ছে কি না। কোনও রেফারেন্সের ক্ষেত্রে এ জাতীয় কোনও চেক প্রয়োজন হয় না, কারণ আমরা ইতিমধ্যে জানি যে ঘোষণার সময় কোনও বস্তুর রেফারেন্স করা বাধ্যতামূলক।
আরেকটি পার্থক্য হ'ল পয়েন্টারটি অন্য কোনও বস্তুতে নির্দেশ করতে পারে তবে রেফারেন্স সর্বদা একই বস্তুর প্রতি উল্লেখ থাকে, আসুন এই উদাহরণটি নেওয়া যাক:
Int a = 6, b = 5;
Int& rf = a;
Cout << rf << endl; // The result we will get is 6, because rf is referencing to the value of a.
rf = b;
cout << a << endl; // The result will be 5 because the value of b now will be stored into the address of a so the former value of a will be erased
আরেকটি বিষয়: যখন আমাদের কাছে কোনও এসটিএল টেম্পলেট জাতীয় টেম্পলেট থাকে তখন শ্রেণীর টেম্পলেট জাতীয় ধরণের টেম্পলেট সর্বদা একটি রেফারেন্স ফিরিয়ে দেয়, কোনও পয়েন্টার নয়, অপারেটরটি ব্যবহার করে সহজেই পড়া বা নতুন মান নির্ধারণের জন্য []:
Std ::vector<int>v(10); // Initialize a vector with 10 elements
V[5] = 5; // Writing the value 5 into the 6 element of our vector, so if the returned type of operator [] was a pointer and not a reference we should write this *v[5]=5, by making a reference we overwrite the element by using the assignment "="
const int& i = 0
।
পার্থক্যটি হ'ল অ-ধ্রুবক পয়েন্টার ভেরিয়েবল (ধ্রুবককে পয়েন্টার দিয়ে বিভ্রান্ত করা উচিত নয়) প্রোগ্রাম সঞ্চালনের সময় কিছু সময় পরিবর্তিত হতে পারে, পয়েন্টার শব্দার্থক ব্যবহার করা প্রয়োজন (&, *) অপারেটরগুলি, যখন রেফারেন্স সূচনাতে সেট করা যেতে পারে কেবলমাত্র (এ কারণেই আপনি কেবল সেগুলি নির্মাণকারী আরম্ভকারী তালিকায় সেট করতে পারেন তবে অন্য কোনওভাবে নয়) এবং সাধারণ মান অ্যাক্সেস শব্দার্থক ব্যবহার করতে পারেন। মূলত রেফারেন্সগুলি অপারেটরদের ওভারলোডিংয়ের পক্ষে সহায়তা করার জন্য প্রবর্তন করা হয়েছিল যেহেতু আমি খুব প্রাচীন কিছু বইতে পড়েছি। যেহেতু কেউ এই থ্রেডে বলেছেন - পয়েন্টারটি 0 বা আপনি যে মানটি চান সেট করতে পারেন। 0 (NULL, nullptr) অর্থ পয়েন্টারটি কিছুই দিয়ে শুরু করা হয়নি। নাল পয়েন্টারকে অবজ্ঞা করার জন্য এটি একটি ত্রুটি। তবে আসলে পয়েন্টারে এমন কোনও মান থাকতে পারে যা কিছু সঠিক মেমোরি অবস্থানের দিকে নির্দেশ করে না। তাদের ঘুরিয়ে রেফারেন্সগুলি চেষ্টা করে যে কোনও ব্যবহারকারীর এমন কোনও রেফারেন্স সূচনা করার অনুমতি না দেয় যা আপনি সর্বদা সঠিক টাইপের মূল্যায়ন সরবরাহ করে এই কারণে যে উল্লেখ করা যায় না। যদিও রেফারেন্স ভেরিয়েবলকে ভুল মেমোরি অবস্থানের সূচনা করার জন্য অনেকগুলি উপায় রয়েছে - বিশদ বিবরণে এই গভীর খনন না করা আপনার পক্ষে ভাল। মেশিন স্তরে পয়েন্টার এবং রেফারেন্স উভয়ই সমানভাবে - পয়েন্টারগুলির মাধ্যমে কাজ করে। আসুন উল্লেখ করা যাক প্রয়োজনীয় উল্লেখগুলি সিনট্যাকটিক চিনি। মূল্যের উল্লেখগুলি এর থেকে আলাদা - এগুলি প্রাকৃতিকভাবে স্ট্যাক / হ্যাপ অবজেক্ট। যদিও রেফারেন্স ভেরিয়েবলকে ভুল মেমোরি অবস্থানের সূচনা করার জন্য অনেকগুলি উপায় রয়েছে - বিশদ বিবরণে এই গভীর খনন না করা আপনার পক্ষে ভাল। মেশিন স্তরে পয়েন্টার এবং রেফারেন্স উভয়ই সমানভাবে - পয়েন্টারগুলির মাধ্যমে কাজ করে। আসুন উল্লেখ করা যাক প্রয়োজনীয় উল্লেখগুলি সিনট্যাকটিক চিনি। মূল্যের উল্লেখগুলি এর থেকে আলাদা - এগুলি প্রাকৃতিকভাবে স্ট্যাক / হ্যাপ অবজেক্ট। যদিও রেফারেন্স ভেরিয়েবলকে ভুল মেমোরি অবস্থানের সূচনা করার জন্য অনেকগুলি উপায় রয়েছে - বিশদ বিবরণে এই গভীর খনন না করা আপনার পক্ষে ভাল। মেশিন স্তরে পয়েন্টার এবং রেফারেন্স উভয়ই সমানভাবে - পয়েন্টারগুলির মাধ্যমে কাজ করে। আসুন উল্লেখ করা যাক প্রয়োজনীয় উল্লেখগুলি সিনট্যাকটিক চিনি। মূল্যের উল্লেখগুলি এর থেকে আলাদা - এগুলি প্রাকৃতিকভাবে স্ট্যাক / হ্যাপ অবজেক্ট।
সহজ কথায়, আমরা বলতে পারি একটি রেফারেন্স একটি ভেরিয়েবলের বিকল্প নাম যেখানে পয়েন্টার একটি ভেরিয়েবল যা অন্য ভেরিয়েবলের ঠিকানা ধারণ করে। যেমন
int a = 20;
int &r = a;
r = 40; /* now the value of a is changed to 40 */
int b =20;
int *ptr;
ptr = &b; /*assigns address of b to ptr not the value */