পার্থক্য কি
- একটি পরামিতি রেফারেন্স দ্বারা পাস
- একটি পরামিতি মান দ্বারা পাস?
দয়া করে আমাকে কিছু উদাহরণ দিতে পারেন?
পার্থক্য কি
দয়া করে আমাকে কিছু উদাহরণ দিতে পারেন?
উত্তর:
প্রথম এবং সর্বাগ্রে, সিএস তত্ত্বে বর্ণিত পার্থক্যটি "রেফারেন্স ভ্যালু রেস। রেফারেন্স দ্বারা পাস" পার্থক্যটি এখন অপ্রচলিত কারণ মূলত "রেফারেন্স দ্বারা পাস" হিসাবে সংজ্ঞায়িত কৌশলটি তখন থেকে অনুকূলে পড়েছে এবং খুব কমই ব্যবহৃত হয়। 1
নতুন ভাষাগুলি 2 একই প্রভাবগুলি অর্জনের জন্য পৃথক (তবে অনুরূপ) কৌশল যুক্ত করতে ব্যবহার করে (নীচে দেখুন) যা বিভ্রান্তির প্রাথমিক উত্স।
বিভ্রান্তির একটি গৌণ উত্স হ'ল "রেফারেন্স দ্বারা পাস" এ, "রেফারেন্স" এর সাধারণ শব্দ "রেফারেন্স" এর চেয়ে সংক্ষিপ্ত অর্থ রয়েছে (কারণ বাক্যাংশটি এর পূর্বাভাস দেয়)।
এখন, খাঁটি সংজ্ঞাটি হ'ল:
যখন কোনও পরামিতি রেফারেন্স দিয়ে পাস হয় , কলার এবং কলি প্যারামিটারের জন্য একই ভেরিয়েবল ব্যবহার করে। যদি কলি প্যারামিটার ভেরিয়েবলটি পরিবর্তন করে, তবে প্রভাবটি কলারের পরিবর্তনশীলটির কাছে দৃশ্যমান।
যখন কোনও প্যারামিটার মান দ্বারা পাস হয় , কলার এবং কলিটির একই মান সহ দুটি স্বতন্ত্র ভেরিয়েবল থাকে । যদি কলি প্যারামিটার ভেরিয়েবলটি পরিবর্তন করে, তবে প্রভাবটি কলারের কাছে দৃশ্যমান নয়।
এই সংজ্ঞাটিতে নোট করার বিষয়গুলি হ'ল:
এখানে "পরিবর্তনশীল" এর অর্থ হ'ল কলারের (স্থানীয় বা গ্লোবাল) ভেরিয়েবলটি নিজেই - অর্থাত যদি আমি একটি স্থানীয় ভেরিয়েবলকে রেফারেন্স দিয়ে পাস করি এবং এটি অর্পণ করি তবে আমি কলারের ভেরিয়েবলটি নিজেই পরিবর্তন করব, উদাহরণস্বরূপ এটি যা পয়েন্টার দিচ্ছে তাতে যা যা ইঙ্গিত করছে তা নয়। ।
"রেফারেন্স দ্বারা পাস" এর "রেফারেন্স" এর অর্থ । সাধারণ "রেফারেন্স" পদটির সাথে পার্থক্য হ'ল এই "রেফারেন্স" অস্থায়ী এবং অন্তর্নিহিত। কলি মূলত যা পায় তা হ'ল "ভেরিয়েবল" যা কোনওভাবে মূলটির মতো "একই"। এই প্রভাবটি কীভাবে সুনির্দিষ্টভাবে অর্জন করা যায় তা অপ্রাসঙ্গিক (উদাহরণস্বরূপ ভাষা কিছু কার্যকরকরণের বিবরণও প্রকাশ করতে পারে - ঠিকানা, পয়েন্টার, ডেরেফারেন্সিং - এগুলি সমস্ত অপ্রাসঙ্গিক; যদি নেট প্রভাবটি এটি হয় তবে এটি পাস-বাই-রেফারেন্স)।
এখন, আধুনিক ভাষায়, ভেরিয়েবলগুলি "রেফারেন্স ধরণের" হয়ে থাকে ( "রেফারেন্স দ্বারা পাস" এর পরে আরও একটি ধারণা উদ্ভাবিত এবং এর দ্বারা অনুপ্রাণিত হয়), প্রকৃত অবজেক্টের ডেটা আলাদাভাবে কোথাও (সাধারণত, গাদা) সংরক্ষণ করা হয়, এবং এর কেবলমাত্র "রেফারেন্স" সর্বদা চলকগুলিতে রাখা হয় এবং পরামিতি হিসাবে পাস করা হয়। 3
এই জাতীয় রেফারেন্সটি পাস করা হ'ল পাস-বাই-ভ্যালুতে আসে কারণ একটি ভেরিয়েবলের মান প্রযুক্তিগতভাবেই রেফারেন্স হয়, রেফার্ড অবজেক্ট নয়। তবে প্রোগ্রামটিতে নেট এফেক্টটি পাস-বাই-ভ্যালু বা পাস-বাই-রেফারেন্সের মতো হতে পারে:
আপনি দেখতে পারেন, এই যুগলের কৌশলগুলি সংজ্ঞা অনুসারে প্রায় একই রকম, কেবলমাত্র একটি মাত্র নির্দেশনার স্তর সহ: কেবল "রেফারেন্সযুক্ত বস্তু" দিয়ে "পরিবর্তনশীল" প্রতিস্থাপন করে।
তাদের পক্ষে কোনও সম্মত নাম নেই, যা "মান দ্বারা কল যেখানে মানটি একটি রেফারেন্স" এর মতো চুক্তিবদ্ধ ব্যাখ্যার দিকে পরিচালিত করে। 1975 সালে, বারবারা লিসকভ " কল-বাই-অবজেক্ট শেয়ারিং " (বা কখনও কখনও কেবল "কল-বাই-ভাগ করে নেওয়া") শব্দটির পরামর্শ দিয়েছিল যদিও এটি কখনও কার্যকর হয় নি। তদুপরি, এই বাক্যাংশগুলির কোনওটিই মূল জোড়ার সাথে সমান্তরাল আঁকেনি। আশ্চর্যের কিছু নেই যে পুরানো শর্তগুলি আরও ভাল কোনওর অনুপস্থিতিতে পুনরায় ব্যবহৃত হয়ে বিভ্রান্তির দিকে পরিচালিত করে। 4
দ্রষ্টব্য : দীর্ঘদিন ধরে, এই উত্তরটি বলত:
বলুন আমি আপনার সাথে একটি ওয়েব পৃষ্ঠা ভাগ করতে চাই। যদি আমি আপনাকে ইউআরএল বলি, আমি রেফারেন্স দিয়ে যাচ্ছি। আমি দেখতে পাচ্ছি একই ওয়েব পৃষ্ঠা দেখতে আপনি সেই URL টি ব্যবহার করতে পারেন। যদি পৃষ্ঠাটি পরিবর্তন করা হয়, তবে আমরা উভয়ই পরিবর্তনগুলি দেখতে পাই। আপনি যদি ইউআরএল মুছে ফেলেন তবে আপনি যা করছেন তা সেই পৃষ্ঠায় আপনার উল্লেখটি নষ্ট করছে - আপনি আসল পৃষ্ঠাটি নিজেই মুছছেন না।
আমি যদি পৃষ্ঠাটি মুদ্রণ করে প্রিন্ট আউট করি তবে আমি মান দিয়ে যাচ্ছি। আপনার পৃষ্ঠাটি মূলটির সংযোগ বিচ্ছিন্ন অনুলিপি। পরবর্তী কোনও পরিবর্তন আপনি দেখতে পাবেন না এবং আপনি যে কোনও পরিবর্তন (যেমন আপনার মুদ্রণে স্ক্রাবলিং) মূল পৃষ্ঠায় প্রদর্শিত হবে না। আপনি যদি মুদ্রণটি নষ্ট করে দেন তবে আপনি আসলে তার সামগ্রীর অনুলিপিটি নষ্ট করেছেন - তবে মূল ওয়েব পৃষ্ঠাটি অক্ষত রয়েছে।
এটি "রেফারেন্স" এর সংকীর্ণ অর্থ ব্যতীত বেশিরভাগ ক্ষেত্রেই সঠিক - এটি উভয়ই অস্থায়ী এবং অন্তর্নিহিত (এটি করার দরকার নেই, তবে সুস্পষ্ট এবং / অথবা অবিচল থাকা অতিরিক্ত বৈশিষ্ট্যগুলি রয়েছে, পাস-বাই-রেফারেন্সের অংশ নয় , উপরে বর্ণিত হিসাবে)। আরও ঘনিষ্ঠ সাদৃশ্যটি আপনাকে মূল নকলটির জন্য একটি দস্তাবেজের অনুলিপি সরবরাহ করবে be
1 আপনি ফোর্টরান বা ভিজ্যুয়াল বেসিকটিতে প্রোগ্রামিং না করলে এটি ডিফল্ট আচরণ নয় এবং আধুনিক ব্যবহারের বেশিরভাগ ভাষায় সত্য কল-বাই-রেফারেন্সও সম্ভব নয়।
2 যথেষ্ট পরিমাণ বয়স্ক ব্যক্তিরাও এটিকে সমর্থন করে
3 বেশ কয়েকটি আধুনিক ভাষায়, সমস্ত ধরণের রেফারেন্স প্রকার। এই দৃষ্টিভঙ্গিটি সিএলইউ ভাষা দ্বারা 1975 সালে প্রবর্তিত হয়েছিল এবং এর পরে পাইথন এবং রুবি সহ আরও অনেক ভাষা গ্রহণ করেছে। এবং আরও অনেকগুলি ভাষা একটি হাইব্রিড পদ্ধতির ব্যবহার করে, যেখানে কিছু প্রকারগুলি "মান ধরণের" এবং অন্যগুলি "রেফারেন্স টাইপ" হয় - তাদের মধ্যে সি #, জাভা এবং জাভাস্ক্রিপ্ট রয়েছে।
4 প্রতি সেটের জন্য উপযুক্ত পুরানো টার্মটি পুনর্ব্যবহার করার ক্ষেত্রে খারাপ কিছু নেই, তবে একসময় এটি পরিষ্কার করে দেওয়া উচিত যে প্রতিবার কোন অর্থটি ব্যবহৃত হচ্ছে। এটি না করা ঠিক ঠিক যা বিভ্রান্তির সৃষ্টি করে।
ফাংশনগুলিতে আর্গুমেন্টগুলি কীভাবে પસાર করা যায় এটি একটি উপায়। রেফারেন্স দিয়ে পাস করার অর্থ হ'ল ডাকা ফাংশনগুলির পরামিতি কলকারীদের পাস হওয়া যুক্তির মতো হবে (মান নয়, তবে পরিচয়টি - নিজেই ভেরিয়েবল)। মান দ্বারা পাস মানে কলযুক্ত ফাংশনগুলির পরামিতি কলকারীদের পাস হওয়া যুক্তির অনুলিপি হবে। মানটি একই হবে, তবে পরিচয় - পরিবর্তনশীল - আলাদা। সুতরাং একটি ক্ষেত্রে ডাকা ফাংশন দ্বারা সম্পন্ন একটি প্যারামিটারে পরিবর্তিত হয়ে যাওয়া আর্গুমেন্টকে পরিবর্তিত করে এবং অন্য ক্ষেত্রে ডাকা ফাংশনটিতে প্যারামিটারের মান পরিবর্তন করে (যা কেবল একটি অনুলিপি)। দ্রুত তাড়াহুড়োয়:
ref
কলার এবং ব্যবহৃত ফাংশন হিসাবে ব্যবহৃত হয়)। জন স্কিট এই একটি চমৎকার ব্যাখ্যা রয়েছে এখানে ।কোড
যেহেতু আমার ভাষা সি ++, আমি এটি এখানে ব্যবহার করব
// passes a pointer (called reference in java) to an integer
void call_by_value(int *p) { // :1
p = NULL;
}
// passes an integer
void call_by_value(int p) { // :2
p = 42;
}
// passes an integer by reference
void call_by_reference(int & p) { // :3
p = 42;
}
// this is the java style of passing references. NULL is called "null" there.
void call_by_value_special(int *p) { // :4
*p = 10; // changes what p points to ("what p references" in java)
// only changes the value of the parameter, but *not* of
// the argument passed by the caller. thus it's pass-by-value:
p = NULL;
}
int main() {
int value = 10;
int * pointer = &value;
call_by_value(pointer); // :1
assert(pointer == &value); // pointer was copied
call_by_value(value); // :2
assert(value == 10); // value was copied
call_by_reference(value); // :3
assert(value == 42); // value was passed by reference
call_by_value_special(pointer); // :4
// pointer was copied but what pointer references was changed.
assert(value == 10 && pointer == &value);
}
এবং জাভাতে একটি উদাহরণ ক্ষতিগ্রস্থ করবে না:
class Example {
int value = 0;
// similar to :4 case in the c++ example
static void accept_reference(Example e) { // :1
e.value++; // will change the referenced object
e = null; // will only change the parameter
}
// similar to the :2 case in the c++ example
static void accept_primitive(int v) { // :2
v++; // will only change the parameter
}
public static void main(String... args) {
int value = 0;
Example ref = new Example(); // reference
// note what we pass is the reference, not the object. we can't
// pass objects. The reference is copied (pass-by-value).
accept_reference(ref); // :1
assert ref != null && ref.value == 1;
// the primitive int variable is copied
accept_primitive(value); // :2
assert value == 0;
}
}
উইকিপিডিয়া
http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_value
http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_reference
এই ছেলে এটি বেশ নখ:
এখানে অনেক উত্তর (এবং বিশেষত সর্বাধিক উচ্চতর উত্তর দেওয়া উত্তর) সত্যই ভুল, যেহেতু তারা "রেফারেন্স দ্বারা কল" এর অর্থ কী তা ভুল বোঝে। বিষয়গুলি সোজা করার জন্য আমার চেষ্টা এখানে।
সহজ কথায়:
রূপক পদে:
নোট করুন যে এই দুটি ধারণাই রেফারেন্স প্রকারের ধারণা (যা জাভাতে সমস্ত ধরণের যা সাব টাইপযুক্ত Object
, এবং সি # তে সমস্ত class
ধরণের), বা সি এর মতো পয়েন্টার ধরণের ধারণা (যা শব্দার্থগতভাবে সমতুল্য ) থেকে সম্পূর্ণ স্বতন্ত্র এবং অরথোগোনাল জাভাটির "রেফারেন্সের ধরণগুলিতে", কেবলমাত্র বিভিন্ন সিনট্যাক্স সহ)
রেফারেন্স টাইপের ধারণাটি কোনও ইউআরএল এর সাথে মিলে যায়: এটি উভয়ই তথ্যের একটি অংশ এবং এটি অন্য তথ্যগুলির সাথে একটি রেফারেন্স (একটি পয়েন্টার , যদি আপনি চান)। আপনার বিভিন্ন URL টির অনেকগুলি অনুলিপি থাকতে পারে এবং তারা সমস্ত ওয়েবসাইটের সাথে লিঙ্ক করে এমন কোনও পরিবর্তন করেন না; যদি ওয়েবসাইট আপডেট হয় তবে প্রতিটি ইউআরএল অনুলিপি এখনও আপডেট হওয়া তথ্যের দিকে নিয়ে যাবে। বিপরীতভাবে, যে কোনও জায়গায় ইউআরএল পরিবর্তন করা URL এর অন্য কোনও লিখিত অনুলিপিকে প্রভাবিত করবে না।
নোট সি ++ "রেফারেন্স" (যেমন একটি ধারণা আছে যে int&
) যে না মত জাভা এবং C # এর "রেফারেন্স ধরনের", কিন্তু হয় "রেফারেন্স দ্বারা কল" মত। জাভা এবং সি # এর "রেফারেন্সের ধরণগুলি", এবং পাইথনের সমস্ত প্রকারগুলি সি এবং সি ++ "পয়েন্টার ধরণের" (যেমন int*
) নামে কল করে।
ঠিক আছে, এখানে দীর্ঘ এবং আরও আনুষ্ঠানিক ব্যাখ্যা।
শুরু করার জন্য, আমি পরিভাষার কয়েকটি গুরুত্বপূর্ণ বিট তুলে ধরতে চাই, আমার উত্তরটি পরিষ্কার করতে সহায়তা করতে এবং আমরা যখন শব্দ ব্যবহার করছি তখন আমরা সকলেই একই ধারণাগুলিতে উল্লেখ করছি তা নিশ্চিত করতে। (বাস্তবে, আমি বিশ্বাস করি যে এই বিষয়গুলি সম্পর্কে প্রচুর বিভ্রান্তি এই শব্দগুলি শব্দগুলি এমনভাবে ব্যবহার করা থেকে উদ্ভূত হয়েছে যাতে উদ্দেশ্যটির অর্থটি পুরোপুরি যোগাযোগ না করা))
শুরু করার জন্য, এখানে কোনও ফাংশন ঘোষণার কয়েকটি সি-জাতীয় ভাষায় একটি উদাহরণ রয়েছে:
void foo(int param) { // line 1
param += 1;
}
এবং এখানে এই ফাংশন কল করার একটি উদাহরণ:
void bar() {
int arg = 1; // line 2
foo(arg); // line 3
}
এই উদাহরণটি ব্যবহার করে, আমি পরিভাষার কয়েকটি গুরুত্বপূর্ণ বিট সংজ্ঞায়িত করতে চাই:
foo
লাইন 1 এ ঘোষিত একটি ফাংশন (জাভা সমস্ত ফাংশন পদ্ধতি তৈরির জন্য জোর দিয়েছিল, তবে সাধারণতা হারানো ছাড়া ধারণাটি একই রকম; সি এবং সি ++ ঘোষণা এবং সংজ্ঞার মধ্যে একটি পার্থক্য তৈরি করে যা আমি এখানে যাব না)param
একটি হয় ফর্ম্যাল প্যারামিটার থেকে foo
, এছাড়াও লাইন 1 ঘোষণাarg
একটি ভেরিয়েবল , বিশেষত ফাংশনের স্থানীয় ভেরিয়েবলbar
, ঘোষণা করা হয় এবং লাইন 2 এ আরম্ভ হয়arg
এছাড়াও একটি হল যুক্তি একটি নির্দিষ্ট করার জন্য আবাহন এর foo
লাইন 3এখানে পৃথক করার জন্য দুটি অত্যন্ত গুরুত্বপূর্ণ ধারণার সেট রয়েছে। প্রথমটি মান বনাম ভেরিয়েবল :
bar
উপরের ফাংশন, লাইন পর int arg = 1;
প্রকাশের arg
হয়েছে মান 1
।final
বা সি # এর ব্যবহার হিসাবে ঘোষিত readonly
) বা গভীরভাবে অপরিবর্তনীয় (যেমন সি ++ এর ব্যবহার const
)।পার্থক্য যুক্ত করার জন্য ধারণাগুলির অপর গুরুত্বপূর্ণ যুগলটি প্যারামিটার বনাম আর্গুমেন্ট :
ইন মান কল , ফাংশন এর আনুষ্ঠানিক পরামিতি ভেরিয়েবল সদ্য ফাংশন আবাহন জন্য তৈরি করা হয়, এবং যা দিয়ে সক্রিয়া করা হয় মান তাদের আর্গুমেন্ট।
এটি ঠিক একইভাবে কাজ করে যে কোনও অন্যান্য ধরণের ভেরিয়েবল মান সহ আরম্ভ হয়। উদাহরণ স্বরূপ:
int arg = 1;
int another_variable = arg;
এখানে arg
এবং another_variable
সম্পূর্ণ স্বাধীন ভেরিয়েবল - তাদের মান একে অপরের থেকে স্বতন্ত্রভাবে পরিবর্তিত হতে পারে। যাইহোক, যেখানে এ another_variable
ঘোষিত হয়, এটি একই মান ধরে রাখার সক্রিয়া করা হয় arg
যা - ঝুলিতে 1
।
যেহেতু এগুলি স্বতন্ত্র পরিবর্তনশীল, তাই পরিবর্তনগুলি another_variable
প্রভাবিত করে না arg
:
int arg = 1;
int another_variable = arg;
another_variable = 2;
assert arg == 1; // true
assert another_variable == 2; // true
এটি আমাদের উপরের উদাহরণের মধ্যে arg
এবং সম্পর্কের ঠিক একই রকম param
, যা আমি এখানে প্রতিসাম্যের জন্য পুনরাবৃত্তি করব:
void foo(int param) {
param += 1;
}
void bar() {
int arg = 1;
foo(arg);
}
এটি ঠিক যেন আমরা কোডটি এইভাবে লিখেছি:
// entering function "bar" here
int arg = 1;
// entering function "foo" here
int param = arg;
param += 1;
// exiting function "foo" here
// exiting function "bar" here
এটি হ'ল, মান দ্বারা কলটি যার সংজ্ঞাযুক্ত বৈশিষ্ট্যটি হ'ল কলি ( foo
এই ক্ষেত্রে) আর্গুমেন্ট হিসাবে মানগুলি গ্রহণ করে তবে তার নিজস্ব পৃথক পৃথক রয়েছে ভেরিয়েবল (আহ্বায়ক ভেরিয়েবল থেকে যারা মানের জন্য bar
এই ক্ষেত্রে)।
উপরের আমার রূপকের কাছে ফিরে যাচ্ছি, আমি bar
এবং আপনি যদি আমি থাকি foo
, যখন আমি আপনাকে কল করি, তখন আমি আপনাকে একটি কাগজের টুকরো দিয়েছিলাম যার উপরে একটি মূল্য লেখা আছে। আপনি কাগজের টুকরো কল param
। সেই মানটি একটি অনুলিপি আমি আমার নোটবুকে (আমার স্থানীয় ভেরিয়েবলগুলি) আমি যে ভেরিয়েবলটিতে লিখেছিarg
।
(একদিকে যেমন: হার্ডওয়্যার এবং অপারেটিং সিস্টেমের উপর নির্ভর করে বিভিন্ন রয়েছে আপনি কীভাবে অন্যের কাছ থেকে কোনও ফাংশনটি কল করবেন সে সম্পর্কে কলিং কনভেনশন রয়েছে The কলিং কনভেনশনটি আমাদের মতো সিদ্ধান্ত নিচ্ছে যে আমি আমার কাগজের টুকরোতে মান লিখি কিনা এবং এটি আপনার হাতে দেব) , বা যদি আপনার কাছে একটি কাগজের টুকরো থাকে যা আমি এটি লিখে রাখি, বা আমি যদি আমাদের উভয়ের সামনে দেয়ালে এটি লিখি This তবে এটি একটি আকর্ষণীয় বিষয়ও, তবে ইতিমধ্যে এই দীর্ঘ উত্তরের সুযোগের বাইরেও))
ইন রেফারেন্স দ্বারা কল , ফাংশন এর আনুষ্ঠানিক পরামিতি কেবল হয় নতুন নাম একই ভেরিয়েবল যে আর্গুমেন্ট হিসাবে কলার সরবরাহ জন্য।
উপরে আমাদের উদাহরণে ফিরে যাওয়া, এটি এর সমতুল্য:
// entering function "bar" here
int arg = 1;
// entering function "foo" here
// aha! I note that "param" is just another name for "arg"
arg /* param */ += 1;
// exiting function "foo" here
// exiting function "bar" here
যেহেতু param
কেবল অন্য নাম arg
- এটি হ'ল তারা একই ভেরিয়েবল , পরিবর্তনগুলি param
প্রতিফলিত হয় arg
। এটি মৌলিক উপায় যেখানে রেফারেন্স দ্বারা কল মান অনুসারে কল থেকে পৃথক হয়।
খুব অল্প ভাষাই রেফারেন্স অনুসারে কল সমর্থন করে তবে সি ++ এটি এর মতো করতে পারে:
void foo(int& param) {
param += 1;
}
void bar() {
int arg = 1;
foo(arg);
}
এই ক্ষেত্রে, param
ঠিক একই নেই মান যেমন arg
, এটি একটি প্রকৃত হয় arg
(ঠিক একটি ভিন্ন নাম দ্বারা) এবং তাই bar
পালন করতে পারে arg
বৃদ্ধি করা হয়েছে।
লক্ষ্য করুন এই হল না কিভাবে জাভা, জাভাস্ক্রিপ্ট, সি, উদ্দেশ্য সি, পাইথন, বা প্রায় অন্য কোন জনপ্রিয় ভাষা আজ কাজ কোন। এর অর্থ এই যে ভাষাগুলি রেফারেন্সের মাধ্যমে কল হয় না , তারা মান অনুসারে কল হয়।
যদি আপনার কাছে যা থাকে তা মান অনুসারে কল হয় তবে প্রকৃত মানটি একটি রেফারেন্স টাইপ বা পয়েন্টার টাইপ হয় তবে "মান" নিজেই খুব আকর্ষণীয় হয় না (যেমন সি তে এটি প্ল্যাটফর্ম-নির্দিষ্ট আকারের কেবল একটি পূর্ণসংখ্যা) - কী আকর্ষণীয় হয় যে মান নির্দেশ করে ।
যদি সেই রেফারেন্স টাইপটি (যা পয়েন্টার) নির্দেশ করে তবে তা পরিবর্তনযোগ্য তারপর একটি আকর্ষণীয় প্রভাব সম্ভব হল: আপনি সরু-টু মান পরিবর্তন করতে পারেন, এবং কলারের কাছে সরু-টু মান, যদিও আহ্বানকারী পর্যবেক্ষন করতে পারে না পরিবর্তন মান্য করতে পারেন পয়েন্টারে নিজেই পরিবর্তিত হয়।
আবার ইউআরএলটির উপমাটি ধার করার জন্য, আমি আপনাকে যে ওয়েবসাইটটি ইউআরএলটির একটি অনুলিপি দিয়েছি তা হ'ল আকর্ষণীয় নয় যদি আমরা দুজনের বিষয়ই ওয়েবসাইটের হয় তবে URL নয়। আপনি যে URL টির অনুলিপিটি নিয়ে স্ক্রাবলিং করছেন তা আমার URL টির অনুলিপিটিকে প্রভাবিত করে না (এবং বাস্তবে জাভা এবং পাইথনের মতো ভাষায় "URL", বা রেফারেন্স টাইপের মান, এটি করতে পারে) মোটেও সংশোধন করা হবে না, কেবল এটিই কেবল নির্দেশিত জিনিসটি পারে)।
বারবারা লিসকভ যখন তিনি সিএলইউ প্রোগ্রামিং ল্যাঙ্গুয়েজ আবিষ্কার করেছিলেন (যার মধ্যে এই শব্দার্থবিজ্ঞান ছিল) তখন বুঝতে পেরেছিলেন যে বিদ্যমান শব্দগুলি "মূল্য দ্বারা কল" এবং "রেফারেন্স দ্বারা কল" এই নতুন ভাষার শব্দার্থতত্ত্ব বর্ণনার জন্য বিশেষভাবে কার্যকর ছিল না। সুতরাং তিনি একটি নতুন শব্দ উদ্ভাবন করেছেন: বস্তু ভাগ করে নেওয়ার মাধ্যমে কল করুন ।
প্রযুক্তিগতভাবে মান দ্বারা কল করা ভাষাগুলি নিয়ে আলোচনা করার সময়, তবে যেখানে ব্যবহারের সাধারণ ধরণগুলি হল রেফারেন্স বা পয়েন্টার ধরণের (এটি: প্রায় প্রতিটি আধুনিক অত্যাবশ্যক, বস্তু-কেন্দ্রিক, বা বহু-দৃষ্টিকোণ প্রোগ্রামিং ল্যাঙ্গুয়েজ), আমি এটির চেয়ে অনেক কম বিভ্রান্তি পেয়েছি কেবল মান দ্বারা কল বা রেফারেন্স দ্বারা কল সম্পর্কে কথা এড়াতে । অবজেক্ট শেয়ার করে কল করতে আটকে থাকুন (বা কেবল অবজেক্ট দ্বারা কল করুন ) এবং কেউ বিভ্রান্ত হবে না। :-)
The first is value versus variable.
The other important pair of concepts to distinguish is parameter versus argument:
২ টি শর্ত বোঝার আগে আপনাকে নিম্নলিখিতগুলি বুঝতে হবে । প্রতিটি বস্তুর 2 টি জিনিস রয়েছে যা এটি আলাদা করতে পারে।
সুতরাং যদি আপনি বলেন employee.name = "John"
জেনে রাখুন যে সম্পর্কে 2 জিনিস আছে name
। এটির মানটি যা "John"
মেমরির মধ্যে এটির অবস্থান যা কিছু হেক্সাডেসিমাল সংখ্যা এটির মতো হতে পারে:0x7fd5d258dd00
।
ভাষার স্থাপত্য বা আপনার অবজেক্টের ধরণের (শ্রেণি, কাঠামো ইত্যাদি) উপর নির্ভর করে আপনি হয় স্থানান্তরিত হবেন "John"
বা0x7fd5d258dd00
পাসিং "John"
মান দ্বারা পাস হিসাবে পরিচিত। পাসিং 0x7fd5d258dd00
রেফারেন্স দ্বারা পাস হিসাবে পরিচিত। যে কেউ এই মেমোরি অবস্থানটির দিকে ইশারা করছে তার মানটির অ্যাক্সেস থাকবে"John"
।
এ সম্পর্কে আরও তথ্যের জন্য, আমি আপনাকে পয়েন্টারকে ডিফারেন্সিং সম্পর্কে পড়ার পরামর্শ দিই এবং কেন ক্লাসের চেয়ে স্ট্রাক্ট (মানের ধরণ) বেছে নিন (রেফারেন্স টাইপ)
এখানে একটি উদাহরণ:
#include <iostream>
void by_val(int arg) { arg += 2; }
void by_ref(int&arg) { arg += 2; }
int main()
{
int x = 0;
by_val(x); std::cout << x << std::endl; // prints 0
by_ref(x); std::cout << x << std::endl; // prints 2
int y = 0;
by_ref(y); std::cout << y << std::endl; // prints 2
by_val(y); std::cout << y << std::endl; // prints 2
}
y
পূর্ববর্তী লাইনে ইতিমধ্যে 2 এ সেট করা হয়েছে। কেন এটি 0 এ ফিরে যাবে?
এটির সর্বাধিক সহজ উপায় হ'ল একটি এক্সেল ফাইলে। আসুন উদাহরণস্বরূপ বলা যাক যে আপনার দুটি সংখ্যক, কোষ A1 এবং B1 অনুসারে 5 এবং 2 রয়েছে এবং আপনি তৃতীয় কক্ষে তাদের যোগফল পেতে চান, আসুন এ 2 বলে দিন। আপনি এটি দুটি উপায়ে করতে পারেন।
হয় এলে সেলে তার মানগুলি 52 2 টাইপ করে কক্ষ এ 2 তে প্রবেশ করে। এই ক্ষেত্রে, কক্ষগুলির A1 বা B1 এর মানগুলি পরিবর্তন হলে, A2 এর যোগফলটি একই থাকে।
অথবা কক্ষগুলি A1 এবং B1 এর "রেফারেন্স" পাশ করে A2 এবং A1 + B1 টাইপ করে সেল এ 2 তে প্রবেশ করুন । এই ক্ষেত্রে, কক্ষগুলির A1 বা B1 এর মানগুলি পরিবর্তন হলে, A2 এর যোগফলটিও পরিবর্তিত হয়।
মান দ্বারা পাস আপনার নির্দিষ্ট করা ভেরিয়েবলে সঞ্চিত ডেটার একটি কপি প্রেরণ করে, রেফারেন্স দিয়ে পাস ভেরিয়েবলের সাথে সরাসরি লিঙ্ক প্রেরণ করে। সুতরাং আপনি যদি রেফারেন্সের মাধ্যমে কোনও ভেরিয়েবল পাস করেন এবং তারপরে আপনি যে ব্লকটি দিয়েছিলেন তার ভিতরে ভেরিয়েবলটি পরিবর্তন করেন তবে আসল ভেরিয়েবলটি পরিবর্তিত হবে। আপনি যদি কেবল মূল্য দিয়ে পাস করেন তবে আসল ভেরিয়েবলটি আপনি যে ব্লকটি দিয়েছিলেন তা দ্বারা পরিবর্তন করা যাবে না তবে কল করার সময় যা কিছু রয়েছে তার একটি অনুলিপি পাবেন।
মান দ্বারা পাস - ফাংশনটি ভেরিয়েবলটি অনুলিপি করে এবং একটি অনুলিপি সহ কাজ করে (যাতে এটি মূল ভেরিয়েবলের কোনও কিছু পরিবর্তন করে না)
রেফারেন্স দ্বারা পাস - ফাংশনটি আসল ভেরিয়েবল ব্যবহার করে, আপনি যদি অন্য ফাংশনে ভেরিয়েবলটি পরিবর্তন করেন তবে এটি আসল ভেরিয়েবলেও পরিবর্তন করে।
উদাহরণ (অনুলিপি করুন এবং ব্যবহার করুন / নিজে চেষ্টা করুন এবং দেখুন):
#include <iostream>
using namespace std;
void funct1(int a){ //pass-by-value
a = 6; //now "a" is 6 only in funct1, but not in main or anywhere else
}
void funct2(int &a){ //pass-by-reference
a = 7; //now "a" is 7 both in funct2, main and everywhere else it'll be used
}
int main()
{
int a = 5;
funct1(a);
cout<<endl<<"A is currently "<<a<<endl<<endl; //will output 5
funct2(a);
cout<<endl<<"A is currently "<<a<<endl<<endl; //will output 7
return 0;
}
এটি সহজ রাখুন, উঁকি দেয়। পাঠ্য দেয়াল একটি খারাপ অভ্যাস হতে পারে।
তাদের মধ্যে একটি প্রধান পার্থক্য হ'ল মান-ধরণের ভেরিয়েবলগুলির স্টোর মান, সুতরাং একটি পদ্ধতি কলটিতে একটি মান-ধরণের ভেরিয়েবল নির্দিষ্ট করে সেই ভেরিয়েবলের মানটির একটি অনুলিপি পদ্ধতিতে পাস করে। রেফারেন্স-টাইপ ভেরিয়েবলগুলি অবজেক্টগুলিতে রেফারেন্স সঞ্চয় করে, সুতরাং একটি আর্গুমেন্ট হিসাবে একটি রেফারেন্স-টাইপ ভেরিয়েবল নির্দিষ্ট করে দেওয়া পদ্ধতিটিকে প্রকৃত রেফারেন্সের একটি অনুলিপি দেয় যা অবজেক্টকে উল্লেখ করে। যদিও রেফারেন্সটি নিজেই মান দ্বারা পাস করা হয়, তবুও পদ্ধতিটি এটি প্রাপ্ত রেফারেন্সটি ব্যবহার করে with এবং সম্ভবত সম্ভবত — মূল অবজেক্টের সাথে ইন্টারঅ্যাক্ট করতে পারে। একইভাবে, কোনও রিটার্ন স্টেটমেন্টের মাধ্যমে কোনও পদ্ধতি থেকে তথ্য ফেরত দেওয়ার সময়, পদ্ধতিটি একটি মান-ধরণের ভেরিয়েবলে সঞ্চিত মানের একটি অনুলিপি বা একটি রেফারেন্স-টাইপ ভেরিয়েবলে সঞ্চিত রেফারেন্সের একটি অনুলিপি প্রদান করে। যখন কোনও রেফারেন্স ফিরে আসে, কলিং পদ্ধতিটি সেই রেফারেন্সটি রেফারেন্সযুক্ত অবজেক্টের সাথে ইন্টারঅ্যাক্ট করতে ব্যবহার করতে পারে। সুতরাং,
সি # তে, রেফারেন্সের মাধ্যমে কোনও ভেরিয়েবল পাস করতে যাতে তথাকথিত পদ্ধতিটি ভেরিয়েবলটির সংশোধন করতে পারে, সি # কীওয়ার্ডগুলি রেফ এবং আউট সরবরাহ করে। প্যারামিটার ঘোষণায় রেফ কীওয়ার্ড প্রয়োগ করা আপনাকে রেফারেন্স দ্বারা কোনও পদ্ধতিতে একটি ভেরিয়েবল পাস করার অনুমতি দেয় called তথাকথিত পদ্ধতিটি কলারটিতে মূল ভেরিয়েবলটি পরিবর্তন করতে সক্ষম হয়। রেফ কীওয়ার্ডটি ভেরিয়েবলগুলির জন্য ব্যবহৃত হয় যা কলিং পদ্ধতিতে ইতিমধ্যে শুরু করা হয়েছে। সাধারণত, যখন কোনও মেথড কলটিতে একটি আর্গুমেন্ট হিসাবে একটি অবিচ্ছিন্ন ভেরিয়েবল থাকে, সংকলক একটি ত্রুটি উত্পন্ন করে। কীওয়ার্ডের সাথে পরামিতির পূর্ববর্তীকরণ একটি আউটপুট প্যারামিটার তৈরি করে। এটি সংকলককে নির্দেশ করে যে আর্গুমেন্টটি রেফারেন্স দ্বারা ডাকা পদ্ধতিতে প্রেরণ করা হবে এবং ডাকা পদ্ধতিটি কলারের মূল ভেরিয়েবলের জন্য একটি মান নির্ধারণ করবে। যদি পদ্ধতিটি কার্যকর করার প্রতিটি সম্ভাব্য পথে আউটপুট প্যারামিটারকে একটি মান নির্ধারণ না করে তবে সংকলক একটি ত্রুটি উত্পন্ন করে। এটি একটি পদ্ধতিতে আর্গুমেন্ট হিসাবে পাস করা হয় এমন একটি অনিবার্য ভেরিয়েবলের জন্য একটি ত্রুটি বার্তা উত্পন্ন করতে সংকলককে বাধা দেয়। একটি পদ্ধতি রিটার্ন স্টেটমেন্টের মাধ্যমে তার কলারে কেবল একটি মানই ফিরিয়ে দিতে পারে তবে একাধিক আউটপুট (রেফ এবং / বা আউট) পরামিতি নির্দিষ্ট করে অনেকগুলি মান ফেরত দিতে পারে।
সি # আলোচনা এবং উদাহরণ এখানে লিঙ্ক পাঠ্য দেখুন
উদাহরণ:
class Dog
{
public:
barkAt( const std::string& pOtherDog ); // const reference
barkAt( std::string pOtherDog ); // value
};
const &
সাধারণত সেরা। আপনি নির্মাণ এবং ধ্বংসের জরিমানা ব্যয় করবেন না। যদি রেফারেন্সটি কনড না হয় তবে আপনার ইন্টারফেসটি পরামর্শ দিচ্ছে যে এটি ডেটাতে পাস হওয়া পরিবর্তন করবে।
সংক্ষেপে, মান দ্বারা উত্তীর্ণ হ'ল এটি যা হয় এবং রেফারেন্সের মাধ্যমে পাস হয় যেখানে হয়।
যদি আপনার মান VAR1 = "শুভ গাই!" হয় তবে আপনি কেবল "শুভ ছেলে!" দেখতে পাবেন। যদি ভিএআর 1 "হ্যাপি গ্যাল!" এ পরিবর্তিত হয় তবে আপনি এটি জানেন না। যদি এটি রেফারেন্স এবং VAR1 পরিবর্তনের মাধ্যমে পাস হয় তবে আপনি পাবেন।
আপনি যদি কোনও ফাংশনে পাস করার পরে মূল ভেরিয়েবলের মান পরিবর্তন করতে না চান তবে ফাংশনটি " পাস বাই ভ্যালু " দিয়ে তৈরি করা উচিত " পরামিতি দিয়ে তৈরি করা উচিত।
তারপরে ফাংশনটির কেবল মান হবে তবে ভেরিয়েবলের পাসের ঠিকানা নয় not ভেরিয়েবলের ঠিকানা ব্যতীত ফাংশনের অভ্যন্তরীণ কোডটি ফাংশনের বাইরের দিক থেকে পরিবর্তনশীল মানটি পরিবর্তন করতে পারে না।
তবে যদি আপনি বাইরে থেকে দেখানো হিসাবে ভেরিয়েবলের মান পরিবর্তন করার ক্ষমতাটি ফাংশনটি দিতে চান তবে আপনাকে রেফারেন্স দিয়ে পাস ব্যবহার করতে হবে । যেহেতু মান এবং ঠিকানা (রেফারেন্স) উভয়ই ফাংশনের অভ্যন্তরে প্রবেশ করানো হয়।
মান দ্বারা পাস মানে আর্গুমেন্ট ব্যবহার করে একটি ফাংশন মান কিভাবে পাস করতে হয়। মান দ্বারা পাস আমরা আমরা উল্লেখ করা চলক মধ্যে সঞ্চিত ডেটা অনুলিপি এবং রেফারেন্স বিসিএসই টি দ্বারা তিনি অনুলিপি করা হয় পাসের চেয়ে ধীর। এর মধ্যে আমরা অনুলিপি করা ডেটাগুলিতে পরিবর্তন করি তবে মূল ডেটা প্রভাবিত হয় না। এনডি পাসের মাধ্যমে রেফারেন্স করুন বা ঠিকানা দ্বারা পাস করুন আমরা ভেরিয়েবলের সরাসরি লিঙ্কটি প্রেরণ করি। বা ভেরিয়েবলের পয়েন্টারটি পাস করা। এটি দ্রুত বিসিএস কম সময় ব্যয় করা হয়
এখানে একটি উদাহরণ যা মান - পয়েন্টার মান - রেফারেন্সের মাধ্যমে পাসের মধ্যে পার্থক্যগুলি দেখায় :
void swap_by_value(int a, int b){
int temp;
temp = a;
a = b;
b = temp;
}
void swap_by_pointer(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void swap_by_reference(int &a, int &b){
int temp;
temp = a;
a = b;
b = temp;
}
int main(void){
int arg1 = 1, arg2 = 2;
swap_by_value(arg1, arg2);
cout << arg1 << " " << arg2 << endl; //prints 1 2
swap_by_pointer(&arg1, &arg2);
cout << arg1 << " " << arg2 << endl; //prints 2 1
arg1 = 1; //reset values
arg2 = 2;
swap_by_reference(arg1, arg2);
cout << arg1 << " " << arg2 << endl; //prints 2 1
}
"রেফারেন্স দ্বারা পাস" পদ্ধতিতে একটি গুরুত্বপূর্ণ সীমাবদ্ধতা রয়েছে । যদি কোনও পরামিতি রেফারেন্স হিসাবে পাস হিসাবে ঘোষিত হয় (সুতরাং এটি & চিহ্ন দ্বারা পূর্বে হয়) এর সাথে সম্পর্কিত প্রকৃত প্যারামিটার অবশ্যই পরিবর্তনশীল হতে হবে ।
আনুষ্ঠানিক পরামিতিটি "মান দ্বারা উত্তীর্ণ" উল্লেখ করে একটি প্রকৃত প্যারামিটার একটি অভিব্যক্তি হতে পারে সাধারণভাবে , সুতরাং এটি কেবল একটি ভেরিয়েবল নয় কেবল আক্ষরিক বা এমনকি কোনও ফাংশন প্রার্থনার ফলাফল ব্যবহারেরও অনুমতি পায়।
ফাংশনটি ভেরিয়েবল ব্যতীত অন্য কোনও ক্ষেত্রে মান রাখতে সক্ষম হয় না। এটি আক্ষরিকের কাছে নতুন মান নির্ধারণ করতে পারে না বা তার ফলাফল পরিবর্তন করতে কোনও অভিব্যক্তিকে বাধ্য করতে পারে না।
পিএস: আপনি বর্তমান থ্রেডে ডিলান বিটি উত্তরও পরীক্ষা করতে পারেন যা এটি সরল কথায় ব্যাখ্যা করে।