c++ - সি++ বই




একটি পয়েন্টার পরিবর্তনশীল এবং C++ একটি রেফারেন্স পরিবর্তনশীল মধ্যে পার্থক্য কি? (20)

একটি সি ++ রেফারেন্স কি ( সি প্রোগ্রামারদের জন্য )

স্বয়ংক্রিয় রেফারেন্স সহ একটি রেফারেন্সটি একটি ধ্রুবক পয়েন্টার (একটি পয়েন্টারের সাথে একটি ধ্রুবক মানের সাথে বিভ্রান্ত হবেন না) হিসাবে বিবেচিত হতে পারে, অর্থাৎ কম্পাইলার আপনার জন্য * অপারেটর প্রয়োগ করবে।

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

C প্রোগ্রামাররা C ++ রেফারেন্সগুলিকে অপছন্দ করতে পারে কারণ এটি যখন স্বাক্ষর ঘটে তখন এটি আর সুস্পষ্ট হবে না বা কোনও যুক্তিটি মান দ্বারা বা ফাংশন স্বাক্ষরগুলি সন্ধান না করেই পয়েন্টার দ্বারা গৃহীত হয়।

C ++ প্রোগ্রামারগুলি পিনার ব্যবহার করে অপছন্দ করতে পারে কারণ সেগুলি অনিরাপদ বলে মনে করা হয় - যদিও রেফারেন্সগুলি একেবারে তুচ্ছ ক্ষেত্রে ব্যতীত ধ্রুবক পয়েন্টারগুলির তুলনায় সত্যিই নিরাপদ নয় - স্বয়ংক্রিয় অভিমুখে সুবিধার অভাব রয়েছে এবং একটি ভিন্ন শব্দার্থিক অর্থ বহন করে।

সি ++ প্রশ্ন থেকে নিম্নলিখিত বিবৃতি বিবেচনা করুন:

যদিও একটি রেফারেন্স প্রায়ই অন্তর্নিহিত সমাবেশ ভাষাতে একটি ঠিকানা ব্যবহার করে প্রয়োগ করা হয়, তবে একটি বস্তুর মজার মজাদার পয়েন্টার হিসাবে একটি রেফারেন্স মনে করবেন না । একটি রেফারেন্স বস্তু। এটি বস্তুর একটি পয়েন্টার নয়, বস্তুর একটি অনুলিপি নয়। এটা বস্তু।

কিন্তু একটি রেফারেন্স আসলে বস্তু ছিল, কিভাবে রেফারেন্স dangling হতে পারে? অপ্রয়োজনীয় ভাষাগুলিতে, পয়েন্টারগুলির তুলনায় রেফারেন্সগুলি 'নিরাপদ' হওয়ার পক্ষে অসম্ভব - সেখানে সাধারণত কেবলমাত্র সীমানা জুড়ে নির্ভরযোগ্যভাবে উদীয়মান মানগুলির কোন উপায় নেই!

কেন আমি সি ++ রেফারেন্স দরকারী বিবেচনা

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

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

আমি রেফারেন্স সিনট্যাক্টিক চিনি হয় জানি, তাই কোড পড়তে এবং লিখতে সহজ।

কিন্তু পার্থক্য কি?

উত্তর এবং নীচের লিঙ্ক থেকে সংক্ষিপ্ত বিবরণ:

  1. একটি পয়েন্টার পুনঃ-নির্ধারণ করা যেতে পারে যে কোনও সময় কতবার একটি রেফারেন্স পুনরায় বাঁধার পরে পুনরায় স্থাপন করা যাবে না।
  2. পয়েন্টার কোথাও ( NULL ) নির্দেশ করতে পারে, একটি রেফারেন্স সবসময় একটি বস্তুর উল্লেখ করে।
  3. আপনি পয়েন্টার সঙ্গে আপনি যেমন একটি রেফারেন্স ঠিকানা গ্রহণ করতে পারবেন না।
  4. সেখানে কোনও "রেফারেন্স গাণিতিক" নেই (তবে আপনি একটি রেফারেন্স দ্বারা নির্দেশিত একটি বস্তুর ঠিকানাটি নিতে পারেন এবং এটিতে &obj + 5 হিসাবে পয়েন্টার গাণিতিক &obj + 5 )।

একটি ভুল ধারণা ব্যাখ্যা করতে:

সি ++ মান একটি কম্পাইলার রেফারেন্সগুলি কিভাবে বাস্তবায়ন করতে পারে তা dictating এড়াতে খুব সতর্কতা অবলম্বন করা হয়, কিন্তু প্রত্যেক সি ++ কম্পাইলার পয়েন্টার হিসাবে রেফারেন্স প্রয়োগ করে। যে, একটি ঘোষণা যেমন:

int &ri = i;

যদি এটি পুরোপুরি অপ্টিমাইজ করা না থাকে তবে পয়েন্টার হিসাবে একই পরিমাণ সঞ্চয়স্থান বরাদ্দ করে এবং সেই সঞ্চয়স্থানে i ঠিকানা রাখে।

সুতরাং, একটি পয়েন্টার এবং একটি রেফারেন্স একই পরিমাণ মেমরি ব্যবহার।

একটি সাধারণ নিয়ম হিসাবে,

  • ফাংশন প্যারামিটার এবং রিটার্ন প্রকারের ব্যবহার দরকারী এবং স্ব-ডকুমেন্টিং ইন্টারফেস প্রদান।
  • অ্যালগরিদম এবং তথ্য কাঠামো বাস্তবায়নের জন্য পয়েন্টার ব্যবহার করুন।

আকর্ষণীয় পড়া:


পয়েন্টার এবং রেফারেন্স মধ্যে পার্থক্য

একটি পয়েন্টার 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

আরেকটি বিন্দু: যখন আমাদের একটি STL টেমপ্লেট মত একটি টেমপ্লেট থাকে তখন এই ধরনের একটি ক্লাসের টেমপ্লেট সবসময় কোনও পয়েন্টার নয়, কোনও পয়েন্টার নয়, সহজ পাঠ্য বা অপারেটর ব্যবহার করে নতুন মান বরাদ্দ করতে []:

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 "="

আপনি যদি সত্যিকারের পেডান্টিক হতে চান তবে একটি রেফারেন্সের সাথে আপনি যা করতে পারেন তা একটি বিষয় যা আপনি পয়েন্টারের সাথে করতে পারবেন না: একটি অস্থায়ী বস্তুর জীবনকাল প্রসারিত করুন। C ++ তে যদি আপনি একটি অস্থায়ী বস্তুর একটি সংখ্যার রেফারেন্স বদ্ধ করেন, তবে সেই বস্তুর জীবনকাল রেফারেন্সের জীবনকাল হয়ে যায়।

std::string s1 = "123";
std::string s2 = "456";

std::string s3_copy = s1 + s2;
const std::string& s3_reference = s1 + s2;

এই উদাহরণে s3_copy অস্থায়ী বস্তুর অনুলিপি করে যা কনক্যাটেনেশনের ফলাফল। যেখানে s3_rence সারবস্তু অস্থায়ী বস্তু হয়ে ওঠে। এটি আসলে একটি অস্থায়ী বস্তুর একটি রেফারেন্স যা এখন রেফারেন্স হিসাবে একই জীবনকাল আছে।

আপনি যদি const ছাড়া এটি চেষ্টা করেন তবে এটি কম্পাইল করতে ব্যর্থ হওয়া উচিত। আপনি একটি অস্থায়ী বস্তুর অ-গণিত রেফারেন্সটি আবদ্ধ করতে পারবেন না, এবং আপনিও সেই বিষয়ে তার ঠিকানা নিতে পারবেন না।


আপনি সবচেয়ে গুরুত্বপূর্ণ অংশ ভুলে গেছেন:

পয়েন্টার ব্যবহার করে সদস্য অ্যাক্সেস ->
রেফারেন্স ব্যবহার করে সদস্য অ্যাক্সেস .

foo->bar স্পষ্টভাবে foo->bar মতো উচ্চতর যে vi স্পষ্টভাবে Emacs থেকে উচ্চতর :-)


জনপ্রিয় মতামতের বিপরীতে, এটি একটি রেফারেন্স থাকতে পারে যা নুল।

int * p = NULL;
int & r = *p;
r = 1;  // crash! (if you're lucky)

অনুমিত, একটি রেফারেন্সের সাথে এটি করা অনেক কঠিন - কিন্তু যদি আপনি এটি পরিচালনা করেন তবে এটি খুঁজে বের করার চেষ্টা করে আপনার চুলটি টিপুন। রেফারেন্সগুলি স্বাভাবিকভাবেই সি ++ তে নিরাপদ নয় !

টেকনিক্যালি এটি একটি অবৈধ রেফারেন্স , একটি নূন্য রেফারেন্স নয়। আপনি C ++ অন্যান্য ভাষায় খুঁজে পেতে পারেন এমন ধারণা হিসাবে নল রেফারেন্সগুলিকে সমর্থন করে না। পাশাপাশি অবৈধ রেফারেন্স অন্যান্য ধরনের আছে। কোনও অবৈধ রেফারেন্স অনির্দিষ্ট আচরণের দর্শকের উত্থাপন করে, ঠিক যেমন একটি অবৈধ পয়েন্টার ব্যবহার করে।

প্রকৃত ত্রুটিটি একটি রেফারেন্সের অ্যাসাইনমেন্টের পূর্বে, নুল পয়েন্টারের ডিফারেন্সিংয়ে থাকে। কিন্তু আমি যে কোনও কম্পাইলার সম্পর্কে সচেতন নই যা সেই অবস্থার কোনও ত্রুটি তৈরি করবে - ত্রুটিটি কোডের পাশাপাশি একটি বিন্দুতে প্রচার করে। যে এই সমস্যা এত জঘন্য করে তোলে। বেশিরভাগ সময়, যদি আপনি একটি নিল পয়েন্টারকে অস্বীকার করেন তবে আপনি সঠিক স্থানে এটি বিপর্যস্ত হন এবং এটি সনাক্ত করতে অনেক ডিবাগিং নেয় না।

উপরে আমার উদাহরণ সংক্ষিপ্ত এবং concreved হয়। এখানে আরো বাস্তব বিশ্বের উদাহরণ।

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 ধারাটি মুছে ফেলা মুক্ত হয় - এটি অনির্দিষ্ট আচরণের সারাংশ।

সমস্যার বাইরে থাকার সঠিক উপায় একটি রেফারেন্স তৈরি করতে একটি নিল পয়েন্টার dereferencing এড়াতে হয়। এখানে এটি সম্পন্ন একটি স্বয়ংক্রিয় উপায়।

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));

ভালো লেখার দক্ষতা সহকারে কারো কাছ থেকে এই সমস্যাটির পুরোনো চেহারাটি দেখুন, জিম হিসলপ এবং হেরব সটারের নুল রেফারেন্স দেখুন।

একটি নিল পয়েন্টার dereferencing এর বিপদগুলির অন্য উদাহরণের জন্য রেমন্ড চেন দ্বারা অন্য প্ল্যাটফর্মে পোর্ট কোডটি চেষ্টা করার সময় অনির্ধারিত আচরণ প্রকাশ করা দেখুন।


প্রকৃতপক্ষে, একটি রেফারেন্স সত্যিই একটি পয়েন্টার মত হয় না।

একটি কম্পাইলার ভেরিয়েবলগুলিতে "রেফারেন্স" রাখে, একটি মেমরি ঠিকানা দিয়ে একটি নাম যুক্ত করে; কম্পাইল করার সময় যে কোন পরিবর্তনশীল নাম একটি মেমরি ঠিকানা অনুবাদ করতে তার কাজ।

যখন আপনি একটি রেফারেন্স তৈরি করেন, আপনি শুধুমাত্র কম্পাইলারকে বলবেন যে আপনি পয়েন্টার পরিবর্তনশীলকে অন্য নামটি বরাদ্দ করেন; তাই রেফারেন্সগুলি "নিল পয়েন্ট" করতে পারে না, কারণ একটি পরিবর্তনশীল হতে পারে না এবং হতে পারে না।

পয়েন্টার ভেরিয়েবল হয়; তারা কিছু অন্যান্য পরিবর্তনশীল ঠিকানা থাকে, বা নাল হতে পারে। গুরুত্বপূর্ণ বিষয় হল একটি পয়েন্টারের একটি মান আছে, যখন একটি রেফারেন্সের কেবল একটি পরিবর্তনশীল রয়েছে যা এটি উল্লেখ করছে।

এখন বাস্তব কোড কিছু ব্যাখ্যা:

int a = 0;
int& b = a;

এখানে আপনি অন্য একটি পরিবর্তনশীল তৈরি হয় না যে a পয়েন্ট; আপনি কেবল মান নাম্বারের মেমরি সামগ্রীতে অন্য নাম যুক্ত করছেন। এই মেমরিতে এখন দুটি নাম রয়েছে, a এবং b , এবং এটি কোনও নামে ব্যবহার করা যেতে পারে।

void increment(int& n)
{
    n = n + 1;
}

int a;
increment(a);

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

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


সিন্ট্যাক্টিক চিনি ছাড়াও, একটি রেফারেন্স একটি const পয়েন্টার (একটি const পয়েন্টার নয় )। যখন আপনি রেফারেন্স পরিবর্তনশীল ঘোষণা করেন তখন এটি আপনাকে অবশ্যই উল্লেখ করতে হবে এবং আপনি পরে এটি পরিবর্তন করতে পারবেন না।

আপডেট: এখন আমি এটি সম্পর্কে আরও কিছু মনে করি, একটি গুরুত্বপূর্ণ পার্থক্য রয়েছে।

একটি কনস্টেবল পয়েন্টারের টার্গেটটি তার ঠিকানা গ্রহণ করে এবং একটি কনস্টেস্ট ব্যবহার করে প্রতিস্থাপিত হতে পারে।

কোনও রেফারেন্সের লক্ষ্যটি ইউবি এর চেয়ে ছোট কোনও জায়গায় প্রতিস্থাপিত হতে পারে না।

এই কম্পাইলার একটি রেফারেন্স উপর আরো অপ্টিমাইজেশান করার অনুমতি দেওয়া উচিত।


আপনি একটি বিমূর্ত বা এমনকি একাডেমিক ফ্যাশন কম্পিউটার ভাষা অধ্যয়ন সঙ্গে পরিচিত না হয়, যদি একটি শব্দার্থিক পার্থক্য যা esoteric প্রদর্শিত হতে পারে।

সর্বোচ্চ স্তরে, রেফারেন্সের ধারণা হল তারা স্বচ্ছ "উপনাম"। আপনার কম্পিউটার তাদের কাজ করার জন্য একটি ঠিকানা ব্যবহার করতে পারে, তবে আপনি এ বিষয়ে চিন্তিত হবেন না: আপনি তাদের বিদ্যমান বস্তুর জন্য "অন্য একটি নাম" হিসাবে মনে করতে চান এবং সিনট্যাক্স এটি প্রতিফলিত করে। তারা পয়েন্টারগুলির তুলনায় কঠোর তবে আপনার কম্পাইলার আপনাকে ঝুঁকিপূর্ণ রেফারেন্স তৈরি করার সময়, যখন আপনি একটি ঝলকপূর্ণ পয়েন্টার তৈরি করতে চান তার চেয়ে বেশি নির্ভরযোগ্যভাবে আপনাকে সতর্ক করতে পারেন।

এর বাইরে, পয়েন্টার এবং রেফারেন্স মধ্যে অবশ্যই কিছু বাস্তব পার্থক্য আছে। তাদের ব্যবহার করার সিনট্যাক্সটি স্পষ্টতই ভিন্ন, এবং আপনি "পুনরায় সীট" রেফারেন্সগুলি, নিরপেক্ষতার রেফারেন্সগুলি বা রেফারেন্সগুলিতে পয়েন্টার রাখতে পারবেন না।


আমি রেফারেন্স ব্যবহার করি না যতক্ষণ না আমার এইগুলির প্রয়োজন হয়:

  • নল পয়েন্টারগুলি একটি সেফিনেল মান হিসাবে ব্যবহার করা যেতে পারে, ফাংশন ওভারলোডিং বা একটি বোলের ব্যবহার এড়াতে প্রায়শই সস্তা উপায়।

  • আপনি একটি পয়েন্টার উপর গাণিতিক করতে পারেন। উদাহরণ স্বরূপ,p += offset;


আরেকটি পার্থক্য হল যে আপনি একটি অকার্যকর প্রকারের পয়েন্টার রাখতে পারেন (এবং এটি কিছু নির্দেশক মানে) কিন্তু অকার্যকর রেফারেন্স নিষিদ্ধ করা হয়।

int a;
void * p = &a; // ok
void & p = a;  //  forbidden

আমি এই বিশেষ পার্থক্য সঙ্গে সত্যিই খুশি বলতে পারেন না। আমি এটি একটি ঠিকানা সঙ্গে কিছু উল্লেখ রেফারেন্স এবং অন্যথায় রেফারেন্সের জন্য একই আচরণ সঙ্গে অনুমোদিত হবে পছন্দ হবে। এটা রেফারেন্স ব্যবহার করে memcpy মত সি লাইব্রেরী ফাংশন কিছু সমতুল্য সংজ্ঞায়িত করার অনুমতি দেবে।


এটি কোনও স্থানের প্রভাব (কোড নির্বাহ না করে) এটি কোনও স্থানটিকে গ্রহণ করবে সেক্ষেত্রে এটি কতটুকু জায়গা নেয় তা কোন ব্যাপার না।

অন্যদিকে, রেফারেন্স এবং পয়েন্টারগুলির মধ্যে একটি বড় পার্থক্য হল যে কক্ষের রেফারেন্সটি অতিক্রম না হওয়া পর্যন্ত স্থায়ীদের রেফারেন্সগুলিকে বাস করার জন্য স্থির করা হয়।

উদাহরণ স্বরূপ:

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!

এটি ভাষা প্রক্রিয়া যা স্কোপগার্ডকে কাজ করতে দেয়।


বিভ্রান্তিতে যোগ দেওয়ার ঝুঁকিতে, আমি কিছু ইনপুট নিক্ষেপ করতে চাই, আমি নিশ্চিত যে কম্পাইলারটি রেফারেন্সগুলিকে কিভাবে প্রয়োগ করে তা নির্ভর করে, তবে জি.সি.সি. ক্ষেত্রে এটি একটি রেফারেন্স শুধুমাত্র স্ট্যাকের উপর একটি পরিবর্তনশীলকে নির্দেশ করতে পারে আসলে সঠিক নয়, উদাহরণস্বরূপ এই নিন:

#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

অতএব একটি রেফারেন্স হুডের নিচে একটি পয়েন্টার হয়, তারা উভয়ই কেবল একটি মেমরি ঠিকানা সঞ্চয় করছে, যেখানে ঠিকানাটি অপ্রাসঙ্গিক বলে মনে হচ্ছে, যদি আপনি স্টড :: cout << str_ref বলা হয় তবে আপনার কী মনে হবে? ডিলিট করার পরে & str_ref? আচ্ছা, সম্ভবত এটি সূক্ষ্ম সংকলন করে, কিন্তু রানটাইম এ সেগমেন্টেশন ফল্টটি কারণ এটি একটি বৈধ পরিবর্তনশীলের দিকে নির্দেশ করে না, আমাদের অবশ্যই একটি ভাঙা রেফারেন্স রয়েছে যা এখনও বিদ্যমান (এটি সুযোগ ছাড়াই না হওয়া পর্যন্ত), তবে এটি নিরর্থক।

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

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

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

মনে রাখবেন, উপরের আমার উদাহরণগুলি ঠিক আছে, উদাহরণগুলি কোন রেফারেন্সটি দেখায় তা উদাহরণস্বরূপ, আপনি যে উপায়ে কোন রেফারেন্স ব্যবহার করতে চান না! একটি রেফারেন্স সঠিক ব্যবহারের জন্য এখানে মাথায় পেরেক আঘাত ইতিমধ্যে এখানে প্রচুর উত্তর আছে


আমি সবসময় সি ++ কোর নির্দেশিকা থেকে this নিয়ম দ্বারা সিদ্ধান্ত :

T * এবং T "কোন আর্গুমেন্ট" একটি বৈধ বিকল্প না হলে T টি পছন্দ করুন


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

এই দুটি প্রোগ্রাম টুকরা বিবেচনা করুন। প্রথম, আমরা অন্য একটি পয়েন্টার বরাদ্দ:

int ival = 1024, ival2 = 2048;
int *pi = &ival, *pi2 = &ival2;
pi = pi2;    // pi now points to ival2

নিয়োগের পরে, ival, পাই দ্বারা চিহ্নিত বস্তু অপরিবর্তিত রয়ে যায়। অ্যাসাইনমেন্ট পাইটির মান পরিবর্তন করে, এটি একটি ভিন্ন বস্তুর দিকে নির্দেশ করে। এখন একটি অনুরূপ প্রোগ্রাম বিবেচনা করুন যা দুটি রেফারেন্স বরাদ্দ করে:

int &ri = ival, &ri2 = ival2;
ri = ri2;    // assigns ival2 to ival

এই নিয়োগটি ival, পরিবর্তে দ্বারা referenced মান, এবং রেফারেন্স নিজেই পরিবর্তন। অ্যাসাইনমেন্টের পরে, দুটি রেফারেন্সগুলি এখনও তাদের মূল বস্তুর উল্লেখ করে, এবং সেই বস্তুর মান এখন একই রকম।


এই tutorial উপর ভিত্তি করে । লিখিত কি এটা আরো স্পষ্ট করে তোলে:

>>> 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


এই প্রোগ্রামটি প্রশ্নের উত্তর বুঝতে সাহায্য করতে পারে। এটি একটি রেফারেন্সের একটি সাধারণ প্রোগ্রাম "j" এবং একটি পয়েন্টার "ptr" যা পরিবর্তনশীল "x" এর দিকে নির্দেশ করে।

#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


একটি রেফারেন্স অন্য পরিবর্তনশীলের জন্য একটি উপনাম, যেখানে একটি পয়েন্টার একটি পরিবর্তনশীল মেমরি ঠিকানা ঝুলিতে। রেফারেন্সগুলি সাধারণভাবে ফাংশন পরামিতি হিসাবে ব্যবহৃত হয় যাতে প্রেরিত বস্তু অনুলিপি নয় তবে বস্তুটি নিজেই হয়।

    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. 

একটি রেফারেন্স অন্য মেমরি দেওয়া অন্য নাম নয়। এটি একটি অননুমোদিত পয়েন্টার যা স্বয়ংক্রিয়ভাবে ব্যবহারের উপর রেফারেন্স করা হয়। মূলত এটি নিচে boils:

int& j = i;

এটা অভ্যন্তরীণভাবে হয়ে যায়

int* const j = &i;

পয়েন্টার এবং রেফারেন্সগুলির মধ্যে একটি মৌলিক পার্থক্য রয়েছে যা আমি যে কেউ দেখেনি তা দেখতে পাইনি: রেফারেন্স ফাংশন আর্গুমেন্টগুলিতে পাস-বাই-রেফারেন্স সেমান্টিক্স সক্ষম করে। পয়েন্টার, যদিও এটি প্রথমে দৃশ্যমান নয় তবে এটি কেবল পাস-বাই-মান শব্দার্থক প্রদান করে। এই নিবন্ধটি খুব সুন্দরভাবে বর্ণনা করা হয়েছে ।

শুভেচ্ছা, & Rzej


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







c++-faq