পয়েন্টার বনাম রেফারেন্স


256

কোনও ফাংশনটির সাথে কাজ করার জন্য আসল ভেরিয়েবল দেওয়ার সময় আরও ভাল অনুশীলন কী হবে:

unsigned long x = 4;

void func1(unsigned long& val) {
     val = 5;            
}
func1(x);

বা:

void func2(unsigned long* val) {
     *val = 5;
}
func2(&x);

আইওউ: একে অপরকে বাছাই করার কোনও কারণ আছে?


1
উল্লেখগুলি অবশ্যই মূল্যবান, তবে আমি সি থেকে এসেছি, যেখানে পয়েন্টারগুলি সর্বত্র রয়েছে। রেফারেন্সের মান বুঝতে প্রথমে পয়েন্টারগুলির সাথে দক্ষ হতে হবে।
জে ডি

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

রেফারেন্স পছন্দ। যখন আপনার পছন্দ না থাকে তখন ব্যবহারকারী পয়েন্টার।
ফেরুঁচিও

উত্তর:


285

আমার থাম্বের নিয়মটি হ'ল:

পয়েন্টারগুলি ব্যবহার করুন যদি আপনি তাদের সাথে পয়েন্টার গাণিতিক করতে চান (উদাহরণস্বরূপ বিন্যাসে অ্যাড্রেস করার জন্য পয়েন্টার ঠিকানাটি বাড়ানো) অথবা আপনাকে যদি কখনও নুল-পয়েন্টারটি পাস করতে হয়।

অন্যথায় রেফারেন্স ব্যবহার করুন।


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

26
পাটিগণিত দ্বারা আপনি কী বোঝাতে চান তা ব্যাখ্যা করুন। একটি নতুন ব্যবহারকারী বুঝতে পারে না যে আপনি পয়েন্টারটি কী নির্দেশ করছে তা সামঞ্জস্য করতে চান।
মার্টিন ইয়র্ক

7
মার্টিন, পাটিগণিতের দ্বারা আমি বোঝাতে চাইছি যে আপনি কোনও কাঠামোর দিকে একটি পয়েন্টার পাস করেছেন তবে জানেন যে এটি কোনও সাধারণ কাঠামো নয় বরং এটির একটি অ্যারে। এক্ষেত্রে আপনি হয় এটি [] ব্যবহার করে সূচী করতে পারেন বা পয়েন্টারে ++ / - ব্যবহার করে পাটিগণিত করতে পারেন। সংক্ষেপে এটাই পার্থক্য।
নীলস পাইপেনব্রিংক

2
মার্টিন, আপনি কেবল পয়েন্টার দিয়ে সরাসরি এটি করতে পারেন। রেফারেন্স সহ না। অবশ্যই আপনি একটি রেফারেন্সের দিকে একটি পয়েন্টার নিতে পারেন এবং
বাস্তবে

1
পলিমারফিজম (উদাহরণস্বরূপ Base* b = new Derived()) সম্পর্কে কী ? এটি এমন একটি মামলার মতো মনে হচ্ছে যা পয়েন্টার ছাড়া পরিচালনা করা যায় না।
ক্রিস রেডফোর্ড

72

আমি সত্যিই মনে করি আপনি কোডিং কোডিং নির্দেশিকা নীচের ফাংশনটি প্রতিষ্ঠা করে উপকৃত হবেন:

  1. অন্য সব জায়গায় হিসাবে, সবসময় হতে const-correct।

    • দ্রষ্টব্য: অন্যান্য জিনিসের মধ্যে এটির অর্থ হল, কেবলমাত্র মূল্য-মূল্য (আইটেম 3 দেখুন) এবং মান দ্বারা পাস করা মানগুলি (আইটেম 4 দেখুন) constনির্দিষ্টকারীর অভাব হতে পারে ।
  2. কেবলমাত্র পয়েন্টার দিয়ে একটি মান পাস করুন যদি মান 0 / NULL বর্তমান প্রসঙ্গে একটি বৈধ ইনপুট হয়।

    • যুক্তি 1: কলার হিসাবে আপনি দেখতে পাচ্ছেন যে আপনি যা পাস তা অবশ্যই ব্যবহারযোগ্য অবস্থায় থাকতে হবে

    • নীতি 2: হিসাবে বলা , আপনি কি জানেন যে যাই হোক না কেন আসে হয় একটি ব্যবহারযোগ্য অবস্থায়। অতএব, সেই মানটির জন্য কোনও NULL- চেক বা ত্রুটি পরিচালনার দরকার নেই।

    • যুক্তি 3: রেশনালস 1 এবং 2 সংকলক প্রয়োগ করা হবে । আপনি যদি পারেন তবে কম্পাইল সময়ে সর্বদা ত্রুটিগুলি ধরুন।

  3. যদি কোনও ফাংশন আর্গুমেন্ট একটি মূল্যবান হয়, তবে এটি রেফারেন্স দিয়ে পাস করুন by

    • যুক্তি: আমরা আইটেম 2 ভাঙতে চাই না ...
  4. মানটি একটি পিওডি ( সমান পুরাতন ডেটাস্ট্রাকচার ) বা যথেষ্ট পরিমাণে ছোট (স্মৃতি অনুসারে) বা অনুলিপি কপি করার জন্য পর্যাপ্ত পরিমাণে ( সময়ানুক্রমিক ) কেবল "মান দিয়ে পাস" নির্বাচন করুন const

    • যুক্তি: অপ্রয়োজনীয় কপিগুলি এড়িয়ে চলুন।
    • দ্রষ্টব্য: যথেষ্ট ছোট এবং যথেষ্ট সস্তা নিখুঁত পরিমাপযোগ্য নয়।

এতে গাইডলাইনটির অভাব রয়েছে যখন: ... "যখন কনস্ট্যান্ড ব্যবহার করতে হবে &" ... গাইডলাইনটি 2 লিখতে হবে "[in] মানগুলির জন্য, কেবলমাত্র পয়েন্টার দিয়ে পাস করুন যদি NUL বৈধ হয় Otherwise অন্যথায় কনস্ট রেফারেন্সটি ব্যবহার করুন (বা" ছোট "অবজেক্টস, অনুলিপি" বা রেফারেন্স যদি এটি একটি [আউট] মান হয় তবে আমি এই পোস্টটি পর্যবেক্ষণ করছি সম্ভাব্যভাবে একটি +1 যোগ করতে
প্যারাসেবল

আইটেম 1 আপনার বর্ণিত কেসটি কভার করে।
জোহান জেরেল

কোনও ডিফল্ট-গঠনমূলক না হলে রেফারেন্সের মাধ্যমে আউট-প্যারামিটারটি পাস করা কিছুটা শক্ত। এটি আমার কোডে বেশ সাধারণ - কোনও ক্রিয়াকলাপের পুরো কারণটি তৈরি হ'ল আউট-অবজেক্ট কারণ এটি অ-তুচ্ছ।
এমসাল্টারস

@ এসএমএলটার্স: আপনি যদি ফাংশনের অভ্যন্তরে মেমরিটি বরাদ্দ করতে যাচ্ছেন (যা আমি মনে করি যা আপনি বোঝাতে চেয়েছিলেন), তবে কেন কেবল বরাদ্দ মেমোরিতে কোনও পয়েন্টার ফিরিয়ে দেওয়া হবে না?
ক্লিস্ট

@ ক্লিস্ট: @ এসএমএলটারদের পক্ষে, অনেকগুলি সম্ভাব্য কারণ রয়েছে। একটি হ'ল আপনি প্রাক আকারের মতো ইতিমধ্যে পূরণের জন্য মেমরি বরাদ্দ করতে পারেন std::vector<>
জোহান জেরেল

24

এটি শেষ পর্যন্ত সাবজেক্টিভ হয়ে শেষ হয় ends এখন পর্যন্ত আলোচনা দরকারী, তবে আমি মনে করি না এর সঠিক বা সিদ্ধান্তমূলক উত্তর আছে। অনেক সময় স্টাইল নির্দেশিকা এবং আপনার প্রয়োজন উপর নির্ভর করবে।

যখন একটি পয়েন্টার সহ কিছু আলাদা ক্ষমতা রয়েছে (কোনও কিছু NUL হতে পারে কি না), একটি আউটপুট প্যারামিটারের জন্য সবচেয়ে বড় ব্যবহারিক পার্থক্য হ'ল নিখুঁত বাক্য গঠন। গুগলের সি ++ স্টাইল গাইড ( https://google.github.io/styleguide/cppguide.html# রেফারেন্স_আর্গুমেন্টস), উদাহরণস্বরূপ, আউটপুট পরামিতিগুলির জন্য কেবল নির্দেশ নির্দেশ দেয় এবং কেবলমাত্র রেফারেন্সকেই কনস্টেন্ট দেয়। যুক্তি পঠনযোগ্যতার একটি: মান সিনট্যাক্স সহ এমন কোনও কিছুর পয়েন্টার অর্থপূর্ণ অর্থ হওয়া উচিত নয়। আমি প্রস্তাব দিচ্ছি না যে এটি অগত্যা সঠিক বা ভুল, তবে আমি মনে করি এখানে মূল বক্তব্যটি এটি স্টাইলের বিষয়, সঠিকতার নয়।


এর অর্থ কী যে রেফারেন্সগুলির মান সিনট্যাক্স রয়েছে তবে পয়েন্টার এর অর্থগত অর্থ?
এরিক অ্যান্ড্রু লুইস

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

একটি ভুলে যাওয়া উচিত নয় যে গুগল সি ++ স্টাইল গাইডটি অনেক বেশি ঘৃণিত।
Deduplicator

7

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


2
আপনি যদি জোহান জেরেল নির্দেশিকা অনুসরণ করেন তবে একটি অ-কনস্ট্যান্ট রেফারেন্সও পরিবর্তনশীল ভেরিয়েবলের বিজ্ঞাপন দেয়, সুতরাং পয়েন্টারের এখানে সুবিধা নেই not
আলেকজান্ডার কন্ড্রাটস্কি

4
@ আলেকজান্ডারকান্ড্রেটস্কি: আপনি বিষয়টিটি হারিয়ে যাচ্ছেন ... আপনি কল সাইটে তাত্ক্ষণিকভাবে দেখতে পাচ্ছেন না যে ডাকা ফাংশনটি প্যারামিটারটিকে constঅ- constরেফারেন্স হিসাবে গ্রহণ করে কিনা , তবে আপনি দেখতে পারেন যে প্যারামিটারটির পাস অলা &xবনাম x, এবং ব্যবহার করুন use প্যারামিটারের পরিবর্তনযোগ্য হতে হবে কিনা তা এনকোড করার জন্য এই কনভেনশন। (এটি বলেছিল, এমন সময় আছে যখন আপনি কোনও constপয়েন্টারটি পাস করতে চান , সুতরাং কনভেনশনটি কেবল একটি ইঙ্গিত's যুক্তিযুক্ত সন্দেহজনক কিছু পরিবর্তন করা যেতে পারে যখন তা হবে না এমন ভাবার চেয়ে কম বিপজ্জনক হবে যখন তা হবে না ....)
টনি ডেলরয়

5

আপনার যদি এমন একটি প্যারামিটার থাকে যেখানে আপনাকে কোনও মানটির অনুপস্থিতি নির্দেশ করতে পারে তবে পরামিতিটিকে একটি পয়েন্টার মান হিসাবে তৈরি করা এবং NULL এ পাস করা সাধারণ অভ্যাস।

বেশিরভাগ ক্ষেত্রে (সুরক্ষার দৃষ্টিকোণ থেকে) এর একটি ভাল সমাধান হ'ল :: alচ্ছিক ব্যবহার করা । এটি আপনাকে রেফারেন্সের মাধ্যমে aচ্ছিক মানগুলিতে এবং ফেরতের মান হিসাবেও যেতে দেয়।

// Sample method using optional as input parameter
void PrintOptional(const boost::optional<std::string>& optional_str)
{
    if (optional_str)
    {
       cout << *optional_str << std::endl;
    }
    else
    {
       cout << "(no string)" << std::endl;
    }
}

// Sample method using optional as return value
boost::optional<int> ReturnOptional(bool return_nothing)
{
    if (return_nothing)
    {
       return boost::optional<int>();
    }

    return boost::optional<int>(42);
}

5

আপনি যখন পারেন তখন একটি রেফারেন্স ব্যবহার করুন, যখন আপনাকে করতে হবে তখন পয়েন্টার ব্যবহার করুন। থেকে সি ++ প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী: "আমি যখন রেফারেন্স ব্যবহার করা উচিত, এবং যখন আমি পয়েন্টার ব্যবহার করা উচিত?"


4

পয়েন্টার

  • পয়েন্টার হ'ল একটি ভেরিয়েবল যা একটি স্মৃতি ঠিকানা রাখে।
  • পয়েন্টার ঘোষণায় একটি বেস টাইপ, একটি * এবং ভেরিয়েবলের নাম থাকে।
  • একটি পয়েন্টার জীবদ্দশায় যেকোন সংখ্যক চলককে নির্দেশ করতে পারে
  • একটি পয়েন্টার যা বর্তমানে কোনও বৈধ মেমরি অবস্থানের দিকে নির্দেশ করে না তার মান নাল দেওয়া হয় (যা শূন্য)

    BaseType* ptrBaseType;
    BaseType objBaseType;
    ptrBaseType = &objBaseType;
  • & এটি একটি অ্যানারি অপারেটর যা তার অপরেন্ডের মেমরি ঠিকানা ফেরত দেয়।

  • ডেরেফারেন্সিং অপারেটর (*) ভেরিয়েবলটিতে সঞ্চিত মান অ্যাক্সেস করতে ব্যবহৃত হয় যা পয়েন্টারটি নির্দেশ করে।

       int nVar = 7;
       int* ptrVar = &nVar;
       int nVar2 = *ptrVar;

উল্লেখ

  • একটি রেফারেন্স (&) একটি বিদ্যমান ভেরিয়েবলের একটি উলের মতো।

  • একটি রেফারেন্স (&) একটি ধ্রুবক পয়েন্টারের মতো যা স্বয়ংক্রিয়ভাবে অর্জিত হয়।

  • এটি সাধারণত ফাংশন আর্গুমেন্ট তালিকা এবং ফাংশন রিটার্ন মানগুলির জন্য ব্যবহৃত হয়।

  • এটি তৈরি হওয়ার সাথে সাথে একটি রেফারেন্স শুরু করতে হবে।

  • একবার কোনও উপাদানের রেফারেন্স শুরু হয়ে গেলে, এটি অন্য কোনও বস্তুর রেফারেন্সে পরিবর্তন করা যায় না।

  • আপনার কাছে নুল রেফারেন্স থাকতে পারে না।

  • একটি কনস্টেন্ট রেফারেন্স একটি কনট ইনটকে উল্লেখ করতে পারে। এটি কনস্টের মান সহ অস্থায়ী পরিবর্তনশীল দ্বারা সম্পন্ন হয়

    int i = 3;    //integer declaration
    int * pi = &i;    //pi points to the integer i
    int& ri = i;    //ri is refers to integer i – creation of reference and initialization

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন


3

একটি রেফারেন্স একটি অন্তর্নিহিত পয়েন্টার। মূলত আপনি রেফারেন্স পয়েন্টের মানটি পরিবর্তন করতে পারেন তবে আপনি রেফারেন্সটি অন্য কোনও দিকে নির্দেশ করতে পারবেন না। সুতরাং আমার 2 সেন্টটি হ'ল যদি আপনি কেবলমাত্র কোনও প্যারামিটারের মান পরিবর্তন করতে চান তবে এটি একটি রেফারেন্স হিসাবে পাস করুন তবে আপনার যদি প্যারামিটারটি পরিবর্তনের প্রয়োজন হয় তবে কোনও পয়েন্টার ব্যবহার করে এটি কোনও ভিন্ন অবজেক্টকে পাস করুন।


3

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


টাইপো: শব্দার্থক, শব্দাবলীর নয়; +1 আমি (সি #) লেখার পরিবর্তে হাইলাইট করার সম্ভাবনা সম্পর্কে একমত, বা & (সি এর ক্ষেত্রে কোনও উল্লেখ নেই)
শিম ছাড়ুন

2

আপনি যে বিষয়বস্তুগুলিতে যাচ্ছেন তাতে পরিবর্তন / রাখতে চান না এমন কোনও কারণ না থাকলে কনড্রাস্ট রেফারেন্স দিয়ে পাস করুন।

এটি বেশিরভাগ ক্ষেত্রে সবচেয়ে কার্যকর পদ্ধতি হবে।

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


2

পয়েন্টার:

  • বরাদ্দ করা যেতে পারে nullptr(বা NULL)।
  • কল সাইটে, আপনাকে অবশ্যই ব্যবহার করতে হবে &যদি আপনার প্রকারটি নিজেই কোনও পয়েন্টার না হয় তবে স্পষ্টভাবে তৈরি করে আপনি নিজের বস্তুকে সংশোধন করছেন।
  • পয়েন্টারগুলি রিবাউন্ড করা যায়।

তথ্যসূত্র:

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

যারা জানে না করার জন্য একটি ছোট পয়েন্ট: nullptr বা শূন্য কেবল একটি 0. stackoverflow.com/questions/462165/...
Serguei Fedorov


0

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

উল্লেখগুলি ফাংশন আর্গুমেন্ট নির্দিষ্ট করার জন্য বিশেষভাবে কার্যকর।

আরও তথ্যের জন্য "বজর্ন স্ট্রস্ট্রপ" (2014) পৃষ্ঠাগুলি 11-12 দ্বারা "সি +++ এর ভ্রমণ" দেখুন

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