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


381

আমি পয়েন্টার বনাম রেফারেন্সের বাক্য গঠন এবং সাধারণ শব্দার্থবিজ্ঞান বুঝতে পারি, তবে যখন কোনও এপিআই-তে রেফারেন্স বা পয়েন্টার ব্যবহার করা কম-বেশি-উপযুক্ত হয় তখন আমি কীভাবে সিদ্ধান্ত নেব?

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

যেমন নিম্নলিখিত কোডে:

void add_one(int& n) { n += 1; }
void add_one(int* const n) { *n += 1; }
int main() {
  int a = 0;
  add_one(a); // Not clear that a may be modified
  add_one(&a); // 'a' is clearly being passed destructively
}

পয়েন্টারটির সাহায্যে এটি সর্বদা (আরও) স্পষ্টভাবে যা ঘটছে তা স্পষ্ট, তাই এপিআই এবং এর মতো যেখানে স্পষ্টতা বড় উদ্বেগের বিষয়গুলি হল পয়েন্টারগুলি উল্লেখের চেয়ে বেশি উপযুক্ত নয়? এর অর্থ কি যখন প্রয়োজন হয় তখনই রেফারেন্সগুলি ব্যবহার করা উচিত (উদাঃ operator++)? এক বা অন্যটির সাথে কোনও পারফরম্যান্স উদ্বেগ রয়েছে?

সম্পাদনা (স্বীকৃত):

NULL মানগুলিকে অনুমতি দেওয়া এবং কাঁচা অ্যারের সাথে কাজ করার পাশাপাশি মনে হয় পছন্দটি ব্যক্তিগত পছন্দকেই কমিয়েছে। আমি নীচের উত্তরটি Google এর সি ++ স্টাইল গাইড হিসাবে উল্লেখ করেছি , কারণ তারা এই মতামতটি উপস্থাপন করে যে "রেফারেন্সগুলি বিভ্রান্তিকর হতে পারে, কারণ তাদের মান সিনট্যাক্স তবে পয়েন্টার শব্দার্থক শব্দ রয়েছে।"

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


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

1
@ স্ক্ননমাস: যথেষ্ট ভাল, আমি বেশিরভাগই টেক্সটমেট ব্যবহার করি। তবুও, আমি মনে করি এটি এক নজরে থেকেই অর্থটি সুস্পষ্ট হয়ে ওঠে fe
সংযোগ

4
add_one(a);যেটি aসংশোধিত হতে চলেছে তা সম্পর্কে অস্পষ্টতা কী ? এটা সঠিক কোডে বলেছেন: এক যোগ
GManNGG

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

1
এটি কেবল পদ্ধতিটির নামকরণের মাধ্যমে ঠিক করা হয়েছে addOneTo(...)। আপনি যদি এটি করতে চান তা না হলে কেবল ঘোষণাটি দেখুন।
স্টেফান

উত্তর:


296

আপনি যেখানেই পারেন সেখানে রেফারেন্স, পয়েন্টারগুলি ব্যবহার করুন।

পয়েন্টারগুলি এড়িয়ে চলুন যতক্ষণ না আপনি পারবেন না।

কারণটি হল যে পয়েন্টারগুলি জিনিসগুলি অনুসরণ / পড়তে আরও কঠিন করে তোলে, অন্য কোনও নির্মাণের চেয়ে কম নিরাপদ এবং অনেক বেশি বিপজ্জনক হেরফের।

সুতরাং থাম্বের নিয়ম হ'ল পয়েন্টারগুলি কেবলমাত্র অন্য কোনও পছন্দ না থাকলে ব্যবহার করা।

উদাহরণস্বরূপ, কোনও বস্তুর কাছে পয়েন্টার ফিরিয়ে দেওয়া একটি বৈধ বিকল্প যখন ফাংশনটি কিছু ক্ষেত্রে নালপ্টরকে ফিরিয়ে দিতে পারে এবং ধারণা করা হয় এটি হবে। এটি বলেছিল, এর থেকে ভাল কিছু অনুরূপ ব্যবহার করা boost::optional

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

আপনার উদাহরণে পয়েন্টারটিকে আর্গুমেন্ট হিসাবে ব্যবহার করার কোনও অর্থ নেই কারণ:

  1. আপনি যদি nullptrযুক্তি হিসাবে সরবরাহ করেন, আপনি অপরিজ্ঞাত-আচরণ-জমিতে যাচ্ছেন;
  2. রেফারেন্স অ্যাট্রিবিউট সংস্করণ 1 (সমস্যাটি সহজ কৌশলগুলি ছাড়াই) সমস্যাটিকে মঞ্জুরি দেয় না।
  3. ব্যবহারকারীর জন্য রেফারেন্স অ্যাট্রিবিউট সংস্করণটি বোঝার জন্য সহজ: আপনাকে একটি বৈধ অবজেক্ট সরবরাহ করতে হবে, এমন কিছু নয় যা শূন্য হতে পারে।

যদি ফাংশনটির আচরণটি কোনও প্রদত্ত বস্তুর সাথে বা তার সাথে কাজ করতে হয়, তবে বিন্যাস হিসাবে পয়েন্টার ব্যবহার করে বোঝানো হয় যে আপনি nullptrযুক্তি হিসাবে পাস করতে পারেন এবং এটি ফাংশনের জন্য ঠিক আছে। এটি ব্যবহারকারী এবং বাস্তবায়নের মধ্যে এক ধরনের চুক্তি।


49
আমি নিশ্চিত নই যে পয়েন্টারগুলি পড়াতে আরও শক্ত করে তোলে? এটি মোটামুটি সহজ ধারণা এবং যখন কোনও কিছুর সংশোধন হওয়ার সম্ভাবনা থাকে তখন তা পরিষ্কার করে দেয়। যদি আমি বলি যে কি ঘটছে তার কোনও ইঙ্গিত নেই যখন এটি পড়া খুব শক্ত, তবে কেন add_one(a)রেফারেন্স দিয়ে সেট করার পরিবর্তে ফলাফলটি ফিরিয়ে দেওয়া উচিত নয়?
সংযোগ

46
@ কনেক: যদি add_one(a)বিভ্রান্তিমূলক হয় তবে এর কারণ হল এটির অনুপযুক্ত নামকরণ করা হয়েছে। add_one(&a)একই বিভ্রান্তি থাকতে পারে, কেবল এখন আপনি পয়েন্টারটি বাড়িয়ে দিচ্ছেন এবং না বস্তুটি। add_one_inplace(a)সমস্ত বিভ্রান্তি এড়ানো হবে।
নিকল বোলাস

20
একটি বিষয়, উল্লেখগুলি মেমরিটিকে উল্লেখ করতে পারে যা পয়েন্টারগুলি যেমন সহজেই চলে যেতে পারে। সুতরাং এগুলি পয়েন্টারগুলির চেয়ে কোনও নিরাপদ নয়। রেফারেন্সগুলি বজায় রাখা এবং পাস করা পয়েন্টারগুলির মতোই বিপজ্জনক হতে পারে।
ডগ টি।

6
@ ক্লেইম আমার অর্থ কাঁচা পয়েন্টার। আমি অর্থ ছিল সি ++ পয়েন্টার আছে, NULLএবং nullptr, এবং এটি একটি কারণ জন্য তাদের রয়েছে। এবং "কখনই পয়েন্টার ব্যবহার করবেন না", এবং / অথবা "NULL কখনই ব্যবহার করবেন না, সর্বদা ব্যবহার করুন boost::optional" দেওয়ার জন্য এটি একটি বিবেচিত বা এমনকি বাস্তবসম্মত পরামর্শ নয় । এটা শুধু উন্মাদ। আমাকে ভুল করবেন না, কাঁচ পয়েন্টারগুলি সি এর চেয়ে কম ঘন ঘন সি -+ এর প্রয়োজন হয়, তবে তবুও তারা দরকারী, তারা কিছু বিপজ্জনক নয় যেমন কিছু সি ++ লোক দাবি করতে চায় (এটিও খুব অতিরঞ্জিত) এবং আবারও: যখন কেবল পয়েন্টার ব্যবহার করা এবং return nullptr;কোনও অনুপস্থিত মান চিহ্নিত করা সহজ হয় ... কেন পুরো বুস্টটি আমদানি করবেন?

5
@ ক্লেইম "NULL ব্যবহার করা খারাপ অভ্যাস" - এখন এটি কেবল হাস্যকর। এবং ifঅপ্রচলিত এবং এক while() { break; }পরিবর্তে ব্যবহার করা উচিত , তাই না? এছাড়াও, চিন্তা করবেন না, আমি বড় কোড ঘাঁটিগুলির সাথে দেখেছি এবং কাজ করেছি এবং হ্যাঁ, আপনি যদি অমনোযোগী হন তবে মালিকানা একটি সমস্যা। আপনি যদি কনভেনশনগুলিতে লেগে থাকেন তবে এগুলি ধারাবাহিকভাবে ব্যবহার করুন এবং মন্তব্য করুন এবং আপনার কোডটি নথিভুক্ত করুন। তবে সর্বোপরি আমার কেবল সি ব্যবহার করা উচিত কারণ আমি সি ++ এর জন্য খুব বোবা, তাই না?

62

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

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

কিছু কোডিং কনভেনশন ( গুগলের মতো ) নির্দেশ দেয় যে সর্বদা পয়েন্টার বা কনফারেন্স রেফারেন্স ব্যবহার করা উচিত, কারণ রেফারেন্সগুলিতে কিছুটা অস্পষ্ট-বাক্য গঠন থাকে: তাদের রেফারেন্সের আচরণ থাকে তবে মান বাক্য গঠন থাকে।


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

44
@ ড্যান: গুগল স্টাইল গাইডটি গুগলের পুরানো কোডের জন্য, এবং আধুনিক কোডিংয়ের জন্য ব্যবহার করা উচিত নয়। আসলে, এটি একটি নতুন প্রকল্পের জন্য একটি খারাপ কোডিং শৈলী।
GManNickG

13
@ কনেক: আমাকে এটি এইভাবে রাখি: নাল একটি পুরোপুরি বৈধ পয়েন্টার মান। যে কোনও জায়গায় পয়েন্টার আছে, আমি এটিকে মান বাতিল করতে পারি। আপনার দ্বিতীয় সংস্করণ অতএব add_oneহয় ভাঙ্গা : add_one(0); // passing a perfectly valid pointer valueKaboom। এটি খালি আছে কিনা তা আপনার পরীক্ষা করা দরকার। কিছু লোক প্রতিক্রিয়া জানাবে: "ভাল আমি কেবল নথী করব যে আমার ফাংশনটি নালার সাথে কাজ করে না" এটি ঠিক আছে, তবে তারপরে আপনি প্রশ্নের উদ্দেশ্যটিকে পরাভূত করবেন: নাল ঠিক আছে কিনা তা দেখার জন্য যদি আপনি ডকুমেন্টেশনের দিকে নজর রাখেন, আপনি ফাংশন ঘোষণাটিও দেখতে পাবেন
GManNickG

8
যদি এটি একটি রেফারেন্স হয়ে থাকে তবে আপনি দেখতে পান যে এটি কেস হবে। এই জাতীয় প্রতিক্রিয়াটি যদিও বিন্দুটিকে মিস করে না: রেফারেন্সগুলি এমন একটি ভাষা স্তরের উপর প্রয়োগ করে যে এটি কোনও বিদ্যমান অবজেক্টকে বোঝায় এবং সম্ভবত নাল নয়, যখন পয়েন্টারগুলিতে এই জাতীয় কোনও বাধা নেই। আমি মনে করি এটি স্পষ্ট যে ভাষা-স্তরের প্রয়োগগুলি ডকুমেন্টেশন-স্তরের প্রয়োগের চেয়ে আরও শক্তিশালী এবং কম ত্রুটি-প্রবণ। কেউ কেউ এটিকে জবাব দেওয়ার চেষ্টা করবেন: "দেখুন, নাল রেফারেন্স: int& i = *((int*)0);এটি কোনও বৈধ প্রতিক্রিয়া নয় the আগের কোডটিতে বিষয়টি পয়েন্টার ব্যবহারের সাথে নিহিত, রেফারেন্সের সাথে নয় Re উল্লেখগুলি কখনই নਾਲ, পিরিয়ড হয় না
GManNGG

12
হ্যালো, আমি মন্তব্যে ভাষা আইনজীবীর অভাব দেখেছি তাই আমাকে প্রতিকার করতে দিন: রেফারেন্সগুলি সাধারণত পয়েন্টারগুলির দ্বারা প্রয়োগ করা হয় তবে মানটি তেমন কিছুই বলে না। কিছু অন্যান্য প্রক্রিয়া ব্যবহার করে একটি বাস্তবায়ন হবে 100% অভিযোগ।
থমাস বনিনি

34

থেকে সি ++ প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী লাইট -

আপনি যখন করতে পারেন তখন রেফারেন্স এবং পয়েন্টারগুলি ব্যবহার করুন।

যখনই আপনার "পুনর্নির্ধারণ" প্রয়োজন হয় না তখন সাধারণত পয়েন্টারগুলির চেয়ে বেশি উল্লেখ করা হয় preferred এর অর্থ সাধারণত হয় যে কোনও শ্রেণীর পাবলিক ইন্টারফেসে রেফারেন্সগুলি সবচেয়ে কার্যকর। রেফারেন্সগুলি সাধারণত কোনও জিনিসের ত্বকে প্রদর্শিত হয় এবং ভিতরে ভিতরে পয়েন্টার থাকে।

উপরের ব্যতিক্রমগুলি যেখানে ফাংশনটির প্যারামিটার বা রিটার্ন মানটির জন্য "সেন্ডিনেল" রেফারেন্স প্রয়োজন - এমন একটি রেফারেন্স যা কোনও অবজেক্টকে রেফার করে না। এটি সাধারণত ফিরে যাওয়ার / পয়েন্টার গ্রহণের মাধ্যমে এবং এনইউএল পয়েন্টারকে এই বিশেষ তাত্পর্য দেওয়ার মাধ্যমে করা হয় (রেফারেন্সগুলি অবশ্যই সর্বদা উরফ অবজেক্টগুলিকে করা উচিত, কোনও এনআরএল পয়েন্টার নয়)।

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


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

1
@ কনেক: নিশ্চয়ই সি প্রোগ্রামার তাদের ভাষার জন্য এটি সঠিক আছে। তবে সি ++ সি হিসাবে বিবেচনা করার ভুল করবেন না এটি সম্পূর্ণ আলাদা ভাষা। আপনি যদি সি ++ কে সি হিসাবে বিবেচনা করেন তবে আপনি সমানতাকে C with class(যা সি ++ নয়) হিসাবে উল্লেখ করা হয় তা লিখে শেষ করেন ।
মার্টিন ইয়র্ক

15

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

  • বহির্গামী বা আউট / আউট প্যারামিটারের জন্য পয়েন্টার ব্যবহার করুন। সুতরাং দেখা যায় যে মানটি পরিবর্তন হতে চলেছে। (আপনি অবশ্যই ব্যবহার করবেন &)
  • NULL প্যারামিটার গ্রহণযোগ্য মান হিসাবে পয়েন্টার ব্যবহার করুন। (এটি constযদি আগত প্যারামিটার হয় তা নিশ্চিত করুন )
  • আগত প্যারামিটারের জন্য রেফারেন্সগুলি ব্যবহার করুন যদি এটি NULL নাও হতে পারে এবং কোনও প্রকারভেদ নয় ( const T&)।
  • নতুন তৈরি হওয়া অবজেক্টটি ফিরিয়ে দেওয়ার সময় পয়েন্টার বা স্মার্ট পয়েন্টার ব্যবহার করুন।
  • পয়েন্টার বা স্মার্ট পয়েন্টারগুলি রেফারেন্সের পরিবর্তে স্ট্রাক্ট বা শ্রেণীর সদস্য হিসাবে ব্যবহার করুন।
  • এলিয়াসিংয়ের জন্য রেফারেন্স ব্যবহার করুন (উদাঃ int &current = someArray[i])

আপনি কোনটি ব্যবহার করুন না কেন, আপনার ফাংশন এবং তাদের পরামিতিগুলির অর্থ স্পষ্ট না হলে ডকুমেন্ট করতে ভুলবেন না।


14

দাবি অস্বীকার: রেফারেন্সগুলি নুল বা "রিবাউন্ড" হতে পারে না (অর্থাত্ থায়া যে জিনিসটির এটির নাম সেটিকে পরিবর্তন করতে পারে না), এটি সত্যই স্বাদের বিষয়টিতে নেমে আসে, তাই আমি বলব না "ইহা ভাল".

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

add_one(&a);

চেয়ে পরিষ্কার হতে পারে

add_one(a);

যেহেতু আপনি জানেন যে সম্ভবত একটি এর মান পরিবর্তন হতে চলেছে। অন্যদিকে যদিও, ফাংশনের স্বাক্ষর

void add_one(int* const n);

হয় কিছুটা পরিষ্কার হয় না: এন একটি একক পূর্ণসংখ্যা বা অ্যারে হতে চলেছে? কখনও কখনও আপনার কেবলমাত্র (দুর্বল দলিলযুক্ত) শিরোনামে অ্যাক্সেস থাকে এবং স্বাক্ষরগুলি পছন্দ হয়

foo(int* const a, int b);

প্রথম দর্শনে ব্যাখ্যা করা সহজ নয়।

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


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

12

অন্যদের ইতিমধ্যে বললেন মতো: সর্বদা ব্যবহার রেফারেন্স, যদি না পরিবর্তনশীল হচ্ছে NULL/ nullptrহয় সত্যিই একটি বৈধ রাষ্ট্র।

বিষয় সম্পর্কে জন কারম্যাকের দৃষ্টিভঙ্গি একই রকম:

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

http://www.altdevblogaday.com/2011/12/24/static-code-analysis/

2012-03-13 সম্পাদনা করুন

ব্যবহারকারী ব্রেট কুহেন্স সঠিকভাবে মন্তব্য করেছেন:

সি ++ 11 মান চূড়ান্ত করা হয়েছে। আমি মনে করি এই থ্রেডের সময়টি উল্লেখ করার সময় হয়েছে যে বেশিরভাগ কোডের উল্লেখ, শেয়ার্ড_পিটার এবং অনন্য_পিটারের সংমিশ্রণে পুরোপুরি ঠিক করা উচিত।

যথেষ্ট সত্য, তবে কাঁচা পয়েন্টারগুলি স্মার্ট পয়েন্টারগুলির সাথে প্রতিস্থাপন করার পরেও প্রশ্নটি এখনও রয়ে গেছে।

উদাহরণস্বরূপ, উভয় std::unique_ptrএবং std::shared_ptrতাদের ডিফল্ট নির্মাতার মাধ্যমে "খালি" পয়েন্টার হিসাবে নির্মিত যেতে পারে:

... মানে যাচাই না করে এগুলি ব্যবহার করা খালি ঝুঁকি নয়, যা জে কারম্যাকের আলোচনার বিষয়টিই তাই is

এবং তারপরে, "মজাদার সমস্যাটি আমরা কীভাবে একটি ফাংশন প্যারামিটার হিসাবে একটি স্মার্ট পয়েন্টারটি পাস করব?"

সি এর জন্য জনের উত্তর সি ++ - উত্সাহিত রেফারেন্সগুলিকে উত্সাহিত :: শেয়ার্ড_পিটার , এবং নীচের মন্তব্যগুলি দেখায় যে তারপরেও অনুলিপি দ্বারা বা রেফারেন্সের মাধ্যমে স্মার্ট পয়েন্টারটি পাস করা যেমনটি চান তেমন পরিষ্কার কাট নয় (আমি নিজের পক্ষে থাকি " বাই-রেফারেন্স "ডিফল্ট হিসাবে, তবে আমি ভুল হতে পারি)।


1
সি ++ 11 মান চূড়ান্ত করা হয়েছে। আমি মনে করি যে এই থ্রেডে উল্লেখ করার সময় এসেছে যে বেশিরভাগ কোডের উল্লেখগুলির সংমিশ্রণ সহ পুরোপুরি ঠিক করা উচিত shared_ptr, এবং unique_ptr। মালিকানা শব্দার্থবিজ্ঞান এবং আউটপুট প্যারামিটার কনভেনশনের এই তিনটি টুকরো এবং স্থিরত্বের সংমিশ্রণ দ্বারা যত্ন নেওয়া হয়। লিগ্যাসি কোড এবং খুব অপ্টিমাইজড অ্যালগরিদম নিয়ে কাজ করার সময় বাদে সি ++ তে কাঁচা পয়েন্টারগুলির প্রয়োজন নেই। যে অঞ্চলগুলিতে তারা ব্যবহৃত হয় সেগুলি যথাসম্ভব এনক্যাপুলেটেড হওয়া উচিত এবং যে কোনও কাঁচা পয়েন্টারকে শব্দার্থগতভাবে উপযুক্ত "আধুনিক" সমতুল্যে রূপান্তর করা উচিত।
ব্রেট কুহন্স

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

@ পোভম্যান: আমি সম্পূর্ণরূপে একমত: মালিকানা যদি ইন্টারফেসের অংশ না হয় (এবং যদি না এটি পরিবর্তন করা হয় তবে তা হওয়া উচিত নয়), তবে আমাদের পরামিতি (বা ফেরতের মান) হিসাবে স্মার্ট পয়েন্টারটি পাস করা উচিত নয়। মালিকানা ইন্টারফেসের অংশ হলে জিনিসটি আরও জটিল হয়। উদাহরণস্বরূপ, সুটার / মায়াররা কীভাবে প্যারামিটার হিসাবে অনন্য_পিত্তর পাস করতে হবে তা নিয়ে বিতর্ক করে: অনুলিপি (সটার) দ্বারা বা আর-মান রেফারেন্স (মায়ার্স) দ্বারা? একটি অ্যান্টিপ্যাটার্ন একটি বিশ্বব্যাপী শেয়ারড_পিটারের কাছে পয়েন্টারটির চারপাশে যাওয়ার উপর নির্ভর করে, সেই পয়েন্টারটি অবৈধ হওয়ার ঝুঁকি নিয়ে (সমাধানটি স্ট্যাকের মধ্যে স্মার্ট পয়েন্টারটি অনুলিপি করা হচ্ছে)
প্যারাসেবল

7

এটি স্বাদের বিষয় নয়। এখানে কিছু নির্দিষ্ট নিয়ম রয়েছে।

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

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

আপনি সংশ্লেষ সংক্রান্ত সুবিধার জন্য একটি সংকলনের একটি উপাদানটি উল্লেখ করতে পারেন, তবে এটি নিরাপদ নয়; উপাদানটি যে কোনও সময় মুছে ফেলা যায়।

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


5

পারফরম্যান্সের যে কোনও পার্থক্য এত ছোট হবে যে এটি কম স্পষ্ট হওয়া পদ্ধতির সাহায্যে ন্যায়সঙ্গত হবে না।

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

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

যখন আপনাকে একটি জটিল ধরণের কোনও মান ফেরত দেওয়ার দরকার হয় তখন আমি উল্লেখগুলি পছন্দ করি। উদাহরণ স্বরূপ:

bool GetFooArray(array &foo); // my preference
bool GetFooArray(array *foo); // alternative

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

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


4

উইকি থেকে অনুলিপি -

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

আমি এটির সাথে 100% সম্মত, এবং এই কারণেই আমি বিশ্বাস করি যে আপনার কেবলমাত্র একটি রেফারেন্স ব্যবহার করা উচিত যখন আপনার যদি এটির করার পক্ষে খুব ভাল কারণ থাকে।


আমি একটি বিশাল পরিমাণেও সম্মত হই, তবে আমি এই দৃষ্টিভঙ্গিটি ঘুরে দেখছি যে NUL পয়েন্টারগুলির সাথে অন্তর্নির্মিত সুরক্ষা হ্রাস খাঁটি বাক্য গঠন সংক্রান্ত উদ্বেগের জন্য কিছুটা ব্যয়বহুল, বিশেষত - যদিও আরও স্পষ্ট - পয়েন্টার বাক্য গঠনটি বেশ কুৎসিত যাহাই হউক না কেন।
সংযোগ

আমি মনে করি পরিস্থিতিটিও একটি গুরুত্বপূর্ণ বিষয় হয়ে উঠবে। আমি মনে করি যখন বর্তমান কোড বেসটি মূলত পয়েন্টার ব্যবহার করে তখন উল্লেখগুলি ব্যবহার করার চেষ্টা করা একটি খারাপ ধারণা হবে। আপনি যদি তাদের রেফারেন্স হিসাবে প্রত্যাশা করেন তবে তাদের এতটা অন্তর্নিহিত সত্যটি সম্ভবত কম গুরুত্বপূর্ণ হতে পারে ..
ব্যবহারকারী 606723

3

মনে রাখার বিষয়গুলি:

  1. পয়েন্টার হতে পারে NULL, তথ্যসূত্র হতে পারে না NULL

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

  3. পয়েন্টার কিছু *সময় রেফারেন্স ব্যবহার করে &

  4. যখন পয়েন্টার গাণিতিক অপারেশন প্রয়োজন হয় পয়েন্টার ব্যবহার করুন।

  5. আপনার একটি শূন্য প্রকারের পয়েন্টার থাকতে পারে তবে একটি শূন্য প্রকারের int a=5; void *p = &a;উল্লেখ থাকতে পারে না।

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

void fun(int *a)
{
    cout<<a<<'\n'; // address of a = 0x7fff79f83eac
    cout<<*a<<'\n'; // value at a = 5
    cout<<a+1<<'\n'; // address of a increment by 4 bytes(int) = 0x7fff79f83eb0
    cout<<*(a+1)<<'\n'; // value here is by default = 0
}
void fun(int &a)
{
    cout<<a<<'\n'; // reference of original a passed a = 5
}
int a=5;
fun(&a);
fun(a);

কখন কী ব্যবহার করবেন তা প্রমাণ করুন

পয়েন্টার : অ্যারে, লিঙ্কলিস্ট, ট্রি বাস্তবায়ন এবং পয়েন্টার পাটিগণিতের জন্য।

তথ্যসূত্র : ফাংশন পরামিতি এবং রিটার্নের ধরণগুলিতে।


2

" যেখানেই সম্ভব রেফারেন্স ব্যবহার করুন " নিয়মে সমস্যা আছে এবং আপনি যদি আরও ব্যবহারের জন্য রেফারেন্স রাখতে চান তবে তা উত্থাপিত হয়। উদাহরণস্বরূপ এটি চিত্রিত করার জন্য, আপনার নিম্নলিখিত ক্লাস রয়েছে তা কল্পনা করুন।

class SimCard
{
    public:
        explicit SimCard(int id):
            m_id(id)
        {
        }

        int getId() const
        {
            return m_id;
        }

    private:
        int m_id;
};

class RefPhone
{
    public:
        explicit RefPhone(const SimCard & card):
            m_card(card)
        {
        }

        int getSimId()
        {
            return m_card.getId();
        }

    private:
        const SimCard & m_card;
};

প্রথমে RefPhone(const SimCard & card)কনস্ট্রাক্টরটিতে একটি রেফারেন্স দিয়ে প্যারামিটার দেওয়া ভাল ধারণা বলে মনে হতে পারে কারণ এটি কনস্ট্রাক্টরের কাছে ভুল / নাল পয়েন্টারগুলি আটকাতে বাধা দেয়। এটি কোনওভাবে স্ট্যাকের উপর ভেরিয়েবল বরাদ্দ এবং আরআইআই থেকে বেনিফিট গ্রহণকে উত্সাহ দেয়।

PtrPhone nullPhone(0);  //this will not happen that easily
SimCard * cardPtr = new SimCard(666);  //evil pointer
delete cardPtr;  //muahaha
PtrPhone uninitPhone(cardPtr);  //this will not happen that easily

তবে অস্থায়ীগুলি আপনার সুখী পৃথিবীকে ধ্বংস করতে আসে।

RefPhone tempPhone(SimCard(666));   //evil temporary
//function referring to destroyed object
tempPhone.getSimId();    //this can happen

সুতরাং যদি আপনি অন্ধভাবে রেফারেন্সগুলিকে আঁকড়ে ধরে থাকেন তবে ধ্বংস হওয়া বস্তুগুলিতে রেফারেন্সগুলি সংরক্ষণ করার সম্ভাবনার জন্য অবৈধ পয়েন্টারগুলি পাস করার সম্ভাবনাটি বাণিজ্য করে রাখেন, যা মূলত একই প্রভাব ফেলে has

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


পয়েন্টার এবং রেফারেন্সের মধ্যে নিম্নলিখিত পার্থক্য রয়েছে।

  1. যখন ভেরিয়েবলগুলি পাস করার কথা আসে, রেফারেন্স দিয়ে পাসটি মান দ্বারা পাসের মতো লাগে তবে পয়েন্টার শব্দার্থক (পয়েন্টারের মতো কাজ করে) থাকে।
  2. রেফারেন্সটি সরাসরি 0 (নাল) এ আরম্ভ করা যায় না।
  3. রেফারেন্স (রেফারেন্স, রেফারেন্স অবজেক্ট নয়) সংশোধন করা যাবে না ("কনস্ট" পয়েন্টারের সমতুল্য)।
  4. কনস্ট্রাক্ট রেফারেন্স অস্থায়ী পরামিতি গ্রহণ করতে পারে।
  5. স্থানীয় কনস্টের উল্লেখগুলি অস্থায়ী বস্তুর আজীবন দীর্ঘায়িত করে

সেগুলি আমলে নেওয়া আমার বর্তমান বিধিগুলি নীচে রয়েছে।

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

3
আপনার উদাহরণের সাথে সমস্যাটি উল্লেখযোগ্য নয় যে উল্লেখগুলি অনিরাপদ নয়, তবে আপনি আপনার ব্যক্তিগত সদস্যদের বাঁচিয়ে রাখার জন্য আপনার অবজেক্টের উদাহরণের আওতার বাইরে কোনও কিছুর উপর নির্ভর করছেন। const SimCard & m_card;কেবল একটি খারাপভাবে লিখিত কোড।
প্লামেনকো

@ প্লামেনকো আমি আশঙ্কা করছি আপনি উদাহরণটির উদ্দেশ্য বুঝতে পারছেন না। const SimCard & m_cardসঠিক কিনা তা প্রসঙ্গে নির্ভর করে। এই পোস্টের বার্তাটি এই নয় যে তথ্যসূত্রগুলি অনিরাপদ ( বার্তাটি হ'ল মন্ত্রটি "যখনই সম্ভব" রেফারেন্সগুলি ব্যবহার করতে অন্ধভাবে থাকা উচিত নয়। উদাহরণটি "যখনই সম্ভব সম্ভব রেফারেন্সগুলি ব্যবহার করুন" মতবাদটির আগ্রাসী ব্যবহারের ফলাফল। এটি পরিষ্কার হওয়া উচিত।
ডক

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

আপনার ব্যবহারিকভাবে কখনও সদস্যদের পছন্দ করা উচিত নয় const SimCard & m_card। আপনি যদি অস্থায়ী সাথে দক্ষ হতে চান তবে explicit RefPhone(const SimCard&& card)কনস্ট্রাক্টর যুক্ত করুন।
প্লামেনকো

@ প্লামেনকো যদি আপনি কিছু প্রাথমিক বোঝার সাথে পড়তে না পারেন তবে আমার পোস্ট দ্বারা ভুল পথে চালিত হওয়ার চেয়ে আপনার আরও বড় সমস্যা রয়েছে। আমি কীভাবে আরও পরিষ্কার হতে পারি তা আমি জানি না। প্রথম বাক্যটি দেখুন। "যখনই সম্ভব" রেফারেন্স ব্যবহার করুন মন্ত্র নিয়ে সমস্যা আছে! আমার পোস্টে আপনি কোথায় এমন বিবৃতি পেয়েছেন যে উল্লেখগুলি খারাপ? আমার পোস্টের শেষে আপনি লেখাগুলি কোথায় রেফারেন্স ব্যবহার করবেন, তাই আপনি কীভাবে এই সিদ্ধান্তে এসেছেন? এটি প্রশ্নের সরাসরি উত্তর নয়?
ডক

1

নীচে কিছু গাইডলাইন দেওয়া হল।

একটি ফাংশন এটিকে পরিবর্তন না করে পাস করা ডেটা ব্যবহার করে:

  1. যদি ডেটা অবজেক্টটি ছোট থাকে যেমন বিল্ট-ইন ডেটা টাইপ বা একটি ছোট কাঠামো, মান দিয়ে এটি পাস করুন।

  2. যদি ডেটা অবজেক্টটি অ্যারে হয় তবে পয়েন্টার ব্যবহার করুন কারণ এটি আপনার একমাত্র পছন্দ। পয়েন্টারটি কনস্টের জন্য পয়েন্টার করুন।

  3. যদি ডেটা অবজেক্টটি একটি ভাল মাপের কাঠামো হয় তবে প্রোগ্রামের দক্ষতা বাড়াতে কনস্ট পয়েন্টার বা কনস্টের রেফারেন্স ব্যবহার করুন a আপনি কোনও কাঠামো বা শ্রেণি নকশার অনুলিপি করার জন্য প্রয়োজনীয় সময় এবং স্থান সংরক্ষণ করুন। পয়েন্টার বা রেফারেন্স কনস্ট করুন।

  4. যদি ডেটা অবজেক্টটি একটি শ্রেণি অবজেক্ট হয় তবে একটি কনস্টের্ট রেফারেন্স ব্যবহার করুন class শ্রেণি নকশার শব্দার্থতত্ত্বগুলিতে প্রায়শই একটি রেফারেন্স ব্যবহার করা প্রয়োজন যা মূল কারণ সি ++ এই বৈশিষ্ট্যটি যুক্ত করেছে hus সুতরাং, শ্রেণি অবজেক্ট আর্গুমেন্টগুলি পাস করার স্ট্যান্ডার্ড উপায় হল রেফারেন্স।

একটি ফাংশন কলিং ফাংশনে ডেটা পরিবর্তন করে:

1. যদি ডেটা অবজেক্টটি অন্তর্নির্মিত ডেটা টাইপ হয় তবে পয়েন্টার ব্যবহার করুন। আপনি যদি ফিক্সিট (& x) এর মতো কোড স্পট করেন যেখানে এক্স একটি অন্তর্নিহিত, এটি খুব স্পষ্ট যে এই ফাংশনটি এক্সকে পরিবর্তন করার ইচ্ছা করে।

2. যদি ডেটা অবজেক্টটি একটি অ্যারে হয় তবে আপনার একমাত্র পছন্দটি ব্যবহার করুন: একটি পয়েন্টার।

৩. যদি ডেটা অবজেক্টটি কাঠামো হয় তবে রেফারেন্স বা পয়েন্টার ব্যবহার করুন।

৪. যদি ডেটা অবজেক্টটি কোনও শ্রেণি অবজেক্ট হয় তবে একটি রেফারেন্স ব্যবহার করুন।

অবশ্যই, এটি কেবল গাইডলাইন এবং বিভিন্ন পছন্দ করার জন্য কারণ থাকতে পারে। উদাহরণস্বরূপ, সিএন মৌলিক ধরণের জন্য রেফারেন্স ব্যবহার করে যাতে আপনি সিন >> এন এর পরিবর্তে সিন >> এন ব্যবহার করতে পারেন।


0

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

int *pInt = new int; // allocates *pInt on the Heap

0

আপনার যথাযথভাবে লিখিত উদাহরণটি দেখতে হবে

void add_one(int& n) { n += 1; }
void add_one(int* const n)
{
  if (n)
    *n += 1;
}

সে কারণেই যদি সম্ভব হয় তবে তথ্যসূত্রগুলি পছন্দনীয় ...


-1

আমার ডাইমটি inুকিয়ে দিন I আমি কেবল একটি পরীক্ষা করেছি। এটায় একটা স্নিগ্ধ। আমি কেবল জি ++ কে রেফারেন্স ব্যবহারের তুলনায় পয়েন্টার ব্যবহার করে একই মিনি-প্রোগ্রামের অ্যাসেমবিলি ফাইলগুলি তৈরি করতে দিই। আউটপুট দেখার সময় এগুলি হুবহু একই রকম। প্রতীকীকরণ ছাড়া অন্য। সুতরাং পারফরম্যান্সের দিকে তাকানো (একটি সাধারণ উদাহরণে) কোনও সমস্যা নেই।

পয়েন্টারস বনাম রেফারেন্সের বিষয়ে এখন। আইএমএইচও আমি মনে করি পরিষ্কারতা সবার উপরে দাঁড়িয়েছে। অন্তর্নিহিত আচরণ পড়ার সাথে সাথেই আমার পায়ের পাতা কুঁকড়ে উঠতে শুরু করে। আমি সম্মত হই যে এটি দুর্দান্ত অন্তর্নিহিত আচরণ যে কোনও রেফারেন্স নুল হতে পারে না।

একটি নল পয়েন্টার নির্ধারণ করা সমস্যা নয়। এটি আপনার অ্যাপ্লিকেশনটি ক্র্যাশ করবে এবং ডিবাগ করা সহজ হবে। একটি বড় সমস্যা হ'ল অবৈজ্ঞানিক পয়েন্টার যা অবৈধ মান রয়েছে। এটি সম্ভবত মেমরির দুর্নীতির ফলে স্পষ্ট উত্স ব্যতীত অপরিজ্ঞাত আচরণের কারণ হয়ে দাঁড়াবে।

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


-2

পয়েন্টারগুলির জন্য, আপনাকে তাদের কোনও কিছুতে নির্দেশ করা প্রয়োজন, সুতরাং পয়েন্টারগুলির জন্য মেমরির জায়গার ব্যয় হয়।

উদাহরণস্বরূপ কোনও ক্রিয়া যা পূর্ণসংখ্যার পয়েন্টার গ্রহণ করে এটি পূর্ণসংখ্য পরিবর্তনশীল গ্রহণ করবে না। সুতরাং আপনাকে প্রথমে ফাংশনে যাওয়ার জন্য একটি পয়েন্টার তৈরি করতে হবে।

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


4
নাঃ। একটি ফাংশন যা পয়েন্টার নেয় তার জন্য পয়েন্টার ভেরিয়েবলের বরাদ্দ প্রয়োজন হয় না: আপনি একটি অস্থায়ী পাস করতে পারেন &address। কোনও রেফারেন্স অবশ্যই মেমোরির জন্য ব্যয় করবে যদি এটি কোনও অবজেক্টের সদস্য হয় এবং প্লাস, সমস্ত বিদ্যমান সংকলক প্রকৃতপক্ষে ঠিকানা হিসাবে রেফারেন্স প্রয়োগ করে, তাই আপনি প্যারামিটার-পাসিং বা ডিফারেন্সিংয়ের ক্ষেত্রে কোনও কিছুই সংরক্ষণ করেন না।
আন্ডারস্কোর_ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.