সি ++ তে রেফারেন্স দিয়ে পাসওয়ার্ড দিয়ে যাওয়ার সুবিধা রয়েছে কি?


225

সি ++ তে রেফারেন্স দিয়ে পাসিংয়ের মাধ্যমে পাস করার সুবিধা কী কী?

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

উদাহরণ:

func(SPRITE *x);

একটি কল সঙ্গে

func(&mySprite);

বনাম

func(SPRITE &x);

একটি কল সঙ্গে

func(mySprite);

newএকটি পয়েন্টার তৈরি করতে এবং মালিকানার ফলস্বরূপ সমস্যাগুলি ভুলে যাবেন না ।
মার্টিন ইয়র্ক

উত্তর:


216

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

এছাড়াও, পয়েন্টারটি দিয়ে যাওয়ার মাধ্যমে আপনি কল সাইটে স্পষ্টভাবে দেখতে পারবেন যা বস্তুটি মান দ্বারা বা রেফারেন্সের মাধ্যমে পাস হয়েছে:

// Is mySprite passed by value or by reference?  You can't tell 
// without looking at the definition of func()
func(mySprite);

// func2 passes "by pointer" - no need to look up function definition
func2(&mySprite);

18
অসম্পূর্ণ উত্তর। পয়েন্টার ব্যবহার অস্থায়ী / প্রচারিত সামগ্রীর ব্যবহারকে অনুমোদন দেবে না, বা পয়েন্ট অবজেক্টের ব্যবহার স্ট্যাকের মতো বস্তু হিসাবে করবে না। এবং এটি পরামর্শ দেবে যে আর্গুমেন্টটি NULL হতে পারে যখন বেশিরভাগ সময় একটি NULL মান নিষিদ্ধ করা উচিত। একটি সম্পূর্ণ উত্তরের জন্য litb এর উত্তর পড়ুন।
প্যার্সেবল

দ্বিতীয় ফাংশন কলটি টীকায় ব্যবহৃত হত func2 passes by reference। যদিও আমি প্রশংসা করি যে আপনি বোঝাতে চেয়েছেন এটি একটি উচ্চ-স্তরের দৃষ্টিভঙ্গি থেকে "রেফারেন্স দ্বারা" পাস হয়েছে, কোড-স্তরের দৃষ্টিকোণে একটি পয়েন্টারটি পেরিয়ে প্রয়োগ করা হয়েছে, এটি অত্যন্ত বিভ্রান্তিকর ছিল (দেখুন স্ট্যাকওভারফ্লো / সেকশনস / ১৩৩৩২৩৫5/২ )।
অরবিটে লাইটনেস রেস

আমি শুধু এই কিনতে না। হ্যাঁ, আপনি একটি পয়েন্টারে পাস করেছেন, সুতরাং এটি অবশ্যই একটি আউটপুট প্যারামিটার হতে হবে, কারণ কোনটি কনস্টেন্ট হতে পারে না?
ডিফোরে

আমাদের সিতে এই উত্তীর্ণ রেফারেন্স নেই? আমি কোডব্লক (মিংডাব্লু) সর্বশেষ সংস্করণ এবং সেটিতে সি প্রকল্প নির্বাচন করে ব্যবহার করছি। এখনও রেফারেন্স (ফানক (ইন্ট এবং এ)) কাজ করে। অথবা এটি সি 99 বা সি 11 এর পরে পাওয়া যায়?
জন হুইলক

1
@ জোনওয়েলক: না, সি এর পাস-বাই-রেফারেন্স মোটেই নেই। func(int& a)মানক কোনও সংস্করণে বৈধ সি নয়। আপনি দুর্ঘটনাক্রমে সম্ভবত আপনার ফাইলগুলি সি ++ হিসাবে সংকলন করছেন।
অ্যাডাম রোজেনফিল্ড

245

পয়েন্টার দ্বারা পাস

  • কলারের ঠিকানাটি নিতে হবে -> স্বচ্ছ নয়
  • একটি 0 মান অর্থ প্রদান করা যেতে পারে nothing। এটি alচ্ছিক যুক্তি সরবরাহ করতে ব্যবহার করা যেতে পারে।

রেফারেন্স দ্বারা পাস

  • কলার সবেমাত্র বস্তুটি পাস করে -> স্বচ্ছ। অপারেটর ওভারলোডিংয়ের জন্য ব্যবহার করতে হবে, যেহেতু পয়েন্টার ধরণের জন্য ওভারলোডিং সম্ভব নয় (পয়েন্টারগুলি অন্তর্নির্মিত প্রকারের)। সুতরাং আপনি string s = &str1 + &str2;পয়েন্টার ব্যবহার করে না করতে পারেন ।
  • কোনও 0 মান সম্ভব নয় -> কল করা ফাংশনটি তাদের চেক করতে হবে না
  • কনস্টের উল্লেখটি অস্থায়ীগুলিও গ্রহণ করে:, void f(const T& t); ... f(T(a, b, c));পয়েন্টারগুলি যেমন ব্যবহার করা যায় না যেহেতু আপনি কোনও অস্থায়ী ঠিকানা নিতে পারেন না।
  • সর্বশেষে তবে কম নয়, রেফারেন্সগুলি ব্যবহার করা সহজ -> বাগের জন্য কম সুযোগ।

7
পয়েন্টার দিয়ে যাওয়ার পরেও 'মালিকানা হস্তান্তরিত হয় নাকি?' প্রশ্ন। রেফারেন্সের ক্ষেত্রে এটি হয় না।
ফ্রেরিচ রাবাবে

43
আমি "বাগের জন্য কম সুযোগ" এর সাথে একমত নই। কল সাইটটি পরিদর্শন করার সময় এবং পাঠক "foo (& গুলি)" দেখেন এটি তাত্ক্ষণিকভাবে পরিষ্কার হয়ে যায় যে এর সংশোধন করা যেতে পারে। আপনি যখন "foo (গুলি)" পড়েন তবে এটি সংশোধন করা যায় কিনা তা মোটেও পরিষ্কার নয়। এটি বাগগুলির একটি প্রধান উত্স। সম্ভবত কোনও নির্দিষ্ট শ্রেণির বাগের সম্ভাবনা কম রয়েছে, তবে সামগ্রিকভাবে, রেফারেন্স দিয়ে পাস করা বাগের বিশাল উত্স।
উইলিয়াম পার্সেল

25
"স্বচ্ছ" বলতে কী বোঝ?
Gbert90

2
@ গবার্ট 90, যদি আপনি কোনও কল সাইটে foo (& a) দেখতে পান, আপনি জানেন foo () একটি পয়েন্টার টাইপ নেয়। যদি আপনি foo (ক) দেখতে পান তবে আপনি জানেন না যে এটি কোনও রেফারেন্স নেয়।
মাইকেল জে। ডেভেনপোর্ট

3
@ মাইকেল জে.ড্যাভেনপোর্ট - আপনার ব্যাখ্যায় আপনি "স্বচ্ছ" পরামর্শ দিয়েছেন "স্পষ্টতই যে কলার একটি পয়েন্টারটি পার করছে, তবে স্পষ্ট নয় যে কলার একটি রেফারেন্সটি পার করছে"। জোহানেস এর পোস্টে, তিনি বলেছেন "পয়েন্টারের মাধ্যমে পাস করা - কলারকে ঠিকানাটি নিতে হবে -> স্বচ্ছ নয়" এবং "রেফারেন্স দিয়ে পাস করুন - কলার কেবল বস্তুটি পাস করেন -> স্বচ্ছ" - যা আপনি যা বলছেন তার থেকে সম্পূর্ণ বিপরীত । আমার মনে হয় Gbert90 এর প্রশ্ন "" স্বচ্ছ "এর অর্থ কী?
শুভ গ্রিন কিড নেপস

66

আমি "cplusplus.com:" এর একটি নিবন্ধ দ্বারা যুক্তি পছন্দ করি

  1. ফাংশনটি প্যারামিটারটি সংশোধন করতে না চাইলে এবং মানটি অনুলিপি করা সহজ হয় (ইনটস, ডাবলস, চর, বুল, ইত্যাদি ... সাধারণ প্রকার। স্টাডি :: স্ট্রিং, এসটিডি :: ভেক্টর এবং অন্যান্য সমস্ত এসটিএল) ধারকগুলি সহজ ধরণের নয়))

  2. মানটি অনুলিপি করার জন্য কনস্ট পয়েন্টার দিয়ে পাস করুন এবং ফাংশনটি নির্দেশিত মানটি পরিবর্তন করতে চায় না এবং NULL একটি কার্যকর, প্রত্যাশিত মান যা ফাংশনটি পরিচালনা করে।

  3. যখন মানটি অনুলিপি করার জন্য ব্যয়বহুল পয়েন্টারটি অতিক্রম করে এবং ফাংশনটি নির্দেশিত মানটি পরিবর্তন করতে চায় এবং NULL একটি কার্যকর, প্রত্যাশিত মান যা ফাংশন পরিচালনা করে।

  4. কনডেন্ট রেফারেন্স দিয়ে পাস করুন যখন মানটি অনুলিপি করা ব্যয়বহুল এবং ফাংশনটি উল্লেখ করা মানটি পরিবর্তন করতে চায় না এবং NUL এর পরিবর্তে কোনও পয়েন্টার ব্যবহার করা হলে এটি বৈধ মান হবে না।

  5. মানটি অনুলিপি করার জন্য অ-কনট্রাক্ট রেফারেন্স দিয়ে পাস করুন এবং ফাংশনটি উল্লেখ করা মানটি পরিবর্তন করতে চায় এবং এর পরিবর্তে কোনও পয়েন্টার ব্যবহার করা হলে NULL একটি বৈধ মান হবে না।

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

http://www.cplusplus.com/articles/z6vU7k9E/

আমি এটি থেকে যা নিচ্ছি তা হল পয়েন্টার বা রেফারেন্স পরামিতি ব্যবহার করা বাছাইয়ের মধ্যে প্রধান পার্থক্য হ'ল যদি NULL একটি গ্রহণযোগ্য মান। এটাই.

মান ইনপুট, আউটপুট, সংশোধনযোগ্য ইত্যাদি হ'ল সর্বোপরি ফাংশন সম্পর্কে ডকুমেন্টেশন / মন্তব্যে থাকা উচিত।


হ্যাঁ, আমার জন্য NULL সম্পর্কিত পদগুলি এখানে প্রধান উদ্বেগ। উদ্ধৃত করার জন্য Thx ..
বাইনারিগু

62

অ্যালেন হলুবের "আপনার নিজের পায়ে গুলি করার জন্য পর্যাপ্ত দড়ি" নিম্নলিখিত 2 টি বিধি তালিকাবদ্ধ করে:

120. Reference arguments should always be `const`
121. Never use references as outputs, use pointers

তিনি সি ++ তে রেফারেন্স যুক্ত করার বিভিন্ন কারণ দেখিয়েছিলেন:

  • তারা অনুলিপি নির্মাণকারী সংজ্ঞায়িত করা প্রয়োজন
  • অপারেটর ওভারলোডগুলির জন্য এগুলি প্রয়োজনীয়
  • const রেফারেন্সগুলি আপনাকে অনুলিপি এড়িয়ে যাওয়ার সময় পাস-বাই-ভ্যালু শব্দার্থবিজ্ঞানের অনুমতি দেয়

তার মূল বিষয়টি হ'ল রেফারেন্সগুলিকে 'আউটপুট' পরামিতি হিসাবে ব্যবহার করা উচিত নয় কারণ কল সাইটে প্যারামিটারটি কোনও রেফারেন্স বা মান প্যারামিটার কিনা তা ইঙ্গিত দেয় না। সুতরাং তার নিয়মটি কেবল constযুক্তি হিসাবে উল্লেখগুলি ব্যবহার করা ।

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


8
এই যুক্তিতে আমার বক্তব্যটি হ'ল যদি ফাংশনটির নামটি ডক্স পরীক্ষা না করেই পুরোপুরি স্পষ্ট করে দেয় যে পরমটি সংশোধন করা হবে, তবে একটি অ-কনস্ট্যান্ট রেফারেন্স ঠিক আছে। সুতরাং ব্যক্তিগতভাবে আমি "getDetails (বিশদ বিবরণ & ফলাফল)" এর অনুমতি দেব। সেখানে একটি পয়েন্টার একটি নাল ইনপুট এর কুৎসিত সম্ভাবনা উত্থাপন।
স্টিভ জেসোপ 19

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

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

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

1
এই নিয়মটি গুগল সি ++ স্টাইল গাইডে ব্যবহৃত হয়: google-styleguide.googlecode.com/svn/trunk/…
আন্তন

9

পূর্ববর্তী পোস্টগুলিতে স্পষ্টতা:


উল্লেখগুলি নন-নাল পয়েন্টার পাওয়ার গ্যারান্টি নয় । (যদিও আমরা তাদের সাথে প্রায়শই এমন আচরণ করি))

ভয়াবহভাবে খারাপ কোড হিসাবে, উডসড খারাপ কোডের পিছনে আপনাকে বের করার সময় , নিম্নলিখিতগুলি সংকলন ও চালিত হবে: (কমপক্ষে আমার সংকলকের নীচে))

bool test( int & a)
{
  return (&a) == (int *) NULL;
}

int
main()
{
  int * i = (int *)NULL;
  cout << ( test(*i) ) << endl;
};

আমার কাছে রেফারেন্সগুলির সাথে থাকা আসল ইস্যুটি অন্যান্য প্রোগ্রামারদের সাথেই রয়েছে, এখন থেকে আইডিয়টস হিসাবে অভিহিত করা হয় , যারা কনস্ট্রাক্টরে বরাদ্দ করেন, ডিস্ট্রাক্টরে ডিলোকট করেন এবং একটি অনুলিপি নির্মাণকারী বা অপারেটর সরবরাহ করতে ব্যর্থ হন = ()।

হঠাৎ ফু (বিএআর বার) এবং ফু (বার এবং বার) এর মধ্যে পার্থক্যের একটি বিশ্ব রয়েছে । (স্বয়ংক্রিয় বিটওয়াইস কপি অপারেশনটি অনুরোধ করা হবে dest

ধন্যবাদ, আধুনিক সংকলকরা একই পয়েন্টারের এই ডাবল-ডিওলোকেশনটি বেছে নেবে। 15 বছর আগে, তারা না। (জিসিসি / জি ++ এর অধীনে, পুরানো উপায়গুলি পুনর্বিবেচনার জন্য setenv MALLOC_CHECK_ 0 ব্যবহার করুন )) ডিসি ইউনিক্সের অধীনে, একই স্মৃতিতে দুটি পৃথক বস্তুর জন্য বরাদ্দ হওয়া ফলাফল Res প্রচুর ডিবাগিং মজা ...


আরও ব্যবহারিকভাবে:

  • রেফারেন্সগুলি গোপন করে যে আপনি অন্য কোথাও সঞ্চিত ডেটা পরিবর্তন করছেন।
  • অনুলিপি করা সহজ কোনও অনুলিপি করা বস্তুর সাথে একটি রেফারেন্সকে বিভ্রান্ত করা।
  • পয়েন্টারগুলি এটি সুস্পষ্ট করে তোলে!

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

1
আমি লিটবের সাথে একমত সত্য হিসাবে, আপনি যে কোডটি আমাদের দেখিয়ে দিচ্ছেন তা হ'ল অন্য যে কোনও কিছুর চেয়ে নাশকতা। "রেফারেন্স" এবং "পয়েন্টার" উভয় স্বরলিপি সহ যেকোন কিছুতে নাশকতার উপায় রয়েছে।
পেরেসারবাল

1
আমি বলেছিলাম এটি "উগ্রশূন্য বাজে কোডের পিছনে আপনাকে বের করে নেবে"! একই শিরাতে আপনার আই = নতুন এফওও থাকতে পারে; আমি মুছুন; পরীক্ষা (* ঝ); আর একটি (দুর্ভাগ্যক্রমে সাধারণ) ঝুঁকির পয়েন্টার / রেফারেন্স উপস্থিতি।
মিঃআর

1
এটা আসলে না dereferencing শূন্য যে সমস্যা, বরং ব্যবহার করে dereferenced (নাল) বস্তু। যেমন, ভাষা-বাস্তবায়নের দৃষ্টিকোণ থেকে পয়েন্টার এবং রেফারেন্সের মধ্যে সত্যই কোনও বাক্য (বাক্য গঠন ছাড়া) নেই। এটি ব্যবহারকারীদের বিভিন্ন প্রত্যাশা রয়েছে।
মিঃআর

2
আপনি যে রেফারেন্সটি ফিরিয়ে দিয়েছিলেন তা নির্বিশেষে, আপনি যে মুহুর্তে বলবেন *i, আপনার প্রোগ্রামের আচরণের সংজ্ঞা রয়েছে। উদাহরণস্বরূপ, সংকলকটি এই কোডটি দেখতে পারে এবং ধরে নিতে পারে "ঠিক আছে, এই কোডটি সমস্ত কোডের পথেই পূর্বনির্ধারিত আচরণ করেছে, সুতরাং এই পুরো ফাংশনটি অবশ্যই নাগম্য be" তারপরে এটি ধরে নেওয়া হবে যে সমস্ত শাখা যা এই ফাংশনে পরিচালিত করে সেগুলি নেওয়া হয়নি। এটি নিয়মিত সম্পাদিত অপ্টিমাইজেশন।
ডেভিড স্টোন

5

এখানে বেশিরভাগ উত্তরই অভিপ্রায় প্রকাশের শর্তে কোনও ফাংশন স্বাক্ষরে কাঁচা পয়েন্টার রাখার সহজাত অস্পষ্টতাকে সম্বোধন করতে ব্যর্থ হয়। সমস্যাগুলি নিম্নলিখিত:

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

  • কলার জানে না যে পয়েন্টারটি মেমোরিটিকে নির্দেশ করে এটি "মালিকানাধীন" কিনা। IE, ফাংশনটির স্মৃতি মুক্ত হওয়া উচিত কিনা। ( foo(new int)- এটি কি স্মৃতি ফুটো?)।

  • কলকারী জানেন nullptrনা যে নিরাপদে ফাংশনে প্রবেশ করতে পারবেন কি না ।

এই সমস্ত সমস্যার সমাধান দ্বারা সমাধান করা হয়:

  • রেফারেন্স সর্বদা একটি একক বস্তুর উল্লেখ করে।

  • রেফারেন্সগুলি তারা যে মেমরিটিকে উল্লেখ করে তার মালিক নয়, এগুলি কেবল মেমরির মধ্যে একটি দৃষ্টিভঙ্গি।

  • তথ্যসূত্রগুলি নਾਲ হতে পারে না।

এটি রেফারেন্সগুলি সাধারণ ব্যবহারের জন্য আরও ভাল প্রার্থী করে তোলে। তবে, উল্লেখগুলি নিখুঁত নয় - কয়েকটি বড় সমস্যা বিবেচনা করতে হবে।

  • কোনও স্পষ্ট নির্দেশনা নেই ction এটি কোনও কাঁচা পয়েন্টার নিয়ে সমস্যা নয়, কারণ আমরা &প্রকৃতপক্ষে কোনও পয়েন্টারটি পাস করছি তা দেখানোর জন্য অপারেটরটি ব্যবহার করতে হবে। উদাহরণস্বরূপ, int a = 5; foo(a);এটি এখানে মোটেও পরিষ্কার নয় যে একটি রেফারেন্স দ্বারা পাস হচ্ছে এবং এটি সংশোধন করা যেতে পারে।
  • Nullability। পয়েন্টারগুলির এই দুর্বলতাও একটি শক্তি হতে পারে, যখন আমরা প্রকৃতপক্ষে আমাদের রেফারেন্সগুলি নালাগুলি করতে চাইstd::optional<T&>বৈধ নয় হিসাবে দেখা (ভাল কারণে), পয়েন্টারগুলি আপনাকে যে নালিয়াটি চান তা দেয়।

সুতরাং দেখে মনে হচ্ছে যে আমরা যখন সুস্পষ্ট ইন্ডিয়ারেশন সহ একটি অযোগ্য রেফারেন্স চাই তখন আমাদের কোনও T*অধিকারের জন্য পৌঁছানো উচিত ? ভুল!

abstractions

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

template <typename T>
struct optional_ref {
  optional_ref() : ptr(nullptr) {}
  optional_ref(T* t) : ptr(t) {}
  optional_ref(std::nullptr_t) : ptr(nullptr) {}

  T& get() const {
    return *ptr;
  }

  explicit operator bool() const {
    return bool(ptr);
  }

private:
  T* ptr;
};

এটি আমি নিয়ে আসা সবচেয়ে সহজ ইন্টারফেস, কিন্তু কার্যকরভাবে এটি কাজ করে। এটি রেফারেন্স সূচনা করার জন্য, কোনও মান বিদ্যমান কিনা তা পরীক্ষা করে এবং মানটি অ্যাক্সেস করার অনুমতি দেয়। আমরা এটি এর মতো ব্যবহার করতে পারি:

void foo(optional_ref<int> x) {
  if (x) {
    auto y = x.get();
    // use y here
  }
}

int x = 5;
foo(&x); // explicit indirection here
foo(nullptr); // nullability

আমরা আমাদের লক্ষ্য অর্জন করেছি! আসুন এখন কাঁচা পয়েন্টারের তুলনায় সুবিধাগুলি দেখুন।

  • ইন্টারফেসটি পরিষ্কারভাবে দেখায় যে রেফারেন্সটি কেবলমাত্র একটি অবজেক্টকে উল্লেখ করা উচিত।
  • স্পষ্টতই এটি যে মেমরিটিকে উল্লেখ করে তার মালিকানা তার নেই, কারণ এতে কোনও ব্যবহারকারীর সংজ্ঞায়িত ডেস্ট্রাক্টর নেই এবং মেমরি মোছার কোনও পদ্ধতি নেই।
  • কলকারী জানেন nullptrযে পাস করা যেতে পারে, যেহেতু ফাংশন লেখক স্পষ্টভাবে একটি জন্য জিজ্ঞাসা করছেনoptional_ref

আমরা এখান থেকে ইন্টারফেসটিকে আরও জটিল করে তুলতে পারি, যেমন সমতা অপারেটর যুক্ত করা, একটি monadic get_orএবং mapইন্টারফেস, একটি পদ্ধতি যা মূল্য পায় বা একটি ব্যতিক্রম, constexprসমর্থন ছুঁড়ে । আপনার দ্বারা এটি করা যেতে পারে।

উপসংহারে, কাঁচা পয়েন্টার ব্যবহার করার পরিবর্তে, আপনার পয়েন্টারগুলিতে আপনার পয়েন্টারগুলি আসলে কী বোঝায় সে সম্পর্কে যুক্তিযুক্ত কারণ এবং কোনও মানক গ্রন্থাগার বিমূর্তিটি উপস্থাপন করুন বা আপনার নিজের লিখুন। এটি আপনার কোডকে উল্লেখযোগ্যভাবে উন্নত করবে।


3

আসলে তা না. অভ্যন্তরীণভাবে, রেফারেন্স দ্বারা উত্তরণটি রেফারেন্সযুক্ত অবজেক্টের ঠিকানাটি প্রয়োজনীয়ভাবে পাস করে সঞ্চালিত হয়। সুতরাং, একটি পয়েন্টার পাস করে কার্যকরভাবে কোনও দক্ষতা অর্জন করার দরকার নেই।

রেফারেন্স দ্বারা পাস করার একটি সুবিধা আছে। আপনার যে কোনও অবজেক্ট / টাইপ যা যা হচ্ছে তা উদাহরণস্বরূপ থাকার নিশ্চয়তা রয়েছে you আপনি যদি কোনও পয়েন্টারে পাস করেন তবে আপনি একটি ন্যূনাল পয়েন্টার পাওয়ার ঝুঁকিটি চালান। পাস-রেফারেন্স ব্যবহার করে, আপনি আপনার ক্রিয়াকলাপের কলকে একটি স্তরকে ন্যূনাল-চেক আপের দিকে চাপ দিচ্ছেন।


1
উভয় একটি সুবিধা এবং অসুবিধা হয়। অনেকগুলি এপিআই NUL পয়েন্টার ব্যবহার করে কিছু দরকারী বোঝার জন্য (অর্থাত NULL টাইমস্পেক চিরকাল অপেক্ষা করে, যখন মান মানে দীর্ঘকাল অপেক্ষা করা হয়)।
গ্রেগ রজার্স 18

1
@ ব্রায়ান: আমি নিট-পিকিং হতে চাই না তবে: আমি বলব না যে রেফারেন্স পাওয়ার সময় একজনের নিশ্চয়তা পাওয়া যায়। ঝুঁকিপূর্ণ রেফারেন্সগুলি এখনও সম্ভব যদি কোনও ফাংশনটির কলকারী একটি ঝুঁকিপূর্ণ পয়েন্টারটিকে রেফারেন্স করে, যা কলিটি জানতে পারে না।
18

কখনও কখনও আপনি এমনকি রেফারেন্স ব্যবহার করে পারফরম্যান্স অর্জন করতে পারেন, যেহেতু তাদের কোনও স্টোরেজ নেওয়ার দরকার নেই এবং তাদের নিজের জন্য কোনও ঠিকানা বরাদ্দ নেই। কোন নির্দেশনা প্রয়োজন।
জোহানেস স্কাউব -

যে প্রোগ্রামগুলিতে ড্যাংলিং রেফারেন্স রয়েছে সেগুলি বৈধ সি ++ নয়। অতএব, হ্যাঁ, কোড পারবেন অনুমান সমস্ত রেফারেন্স বৈধ।
কনরাড রুডলফ

2
আমি স্পষ্টভাবে একটি নাল পয়েন্টারকে উপস্থাপন করতে পারি এবং সংকলকটি বলতে সক্ষম হবে না ... যদি সংকলক এটি "অবৈধ সি ++" বলতে না পারে, তবে তা কি সত্যই অবৈধ?
rmeador
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.