در این مطلب میخوایم اول به بررسی تفاوت بین Argument و Parameter بپردازیم بعد تفاوت بین Call By Refrence و Call By Value رو در زبان های برنامه نویسی بررسی کنیم
در زبان های برنامه نویسی اگر ما بخوایم یه تابعی رو صدا بزنیم و مقادیری رو بهش بفرستیم چند تا اصطلاح داریم :
def sum(p,o):
sum=p+o
return sum
a=int(input("1st Num: "))
b=int(input("2nd Num: "))
print(sum(a,b))
در اینجا اگر دقت کنید وقتی که ما میخوایم یه تابعی رو صدا بزنیم یه مقادیری رو بهش اصطلاحا پاس میدیم (Pass) و در اینجا دوتا اصطلاح هست ، مقادیر a و b ای که ما میخوایم پاس بدیم و در حال فرستاده شدنه میشه ارگومان ، و مقادیری که داخل تابع دریافت میشه و روش پردازش انجام میشه ، پارامتر نام میگیره ، یعنی p و o در خط 1 پارامتر هستن و a و b در خط 7 ارگومان هستن (این مفهوم در تمامی زبان های برنامه نویسی وجود داره)
در زبان های برنامه نویسی ما یه مفهوم داریم ، و اونم اینه که ارگومانی که ما پاس میدیم به تابع ، وقتی تابع اون پارامتر رو میگیره و روش عملیات انجام میده داخل خودش، روی مقادیر اون پارامتر تغییری اعمال کنه و ارگومانم عوض بشه به این نوع پاس دادن میگن call by refrence و اگر مقادیر ارگومان و پارامتر متفاوت باشن میشه call by value ، به زبانی دیگر : اگر ما موقعی که میخوایم مقادیر رو پاس بدیم به تابع ، از مقادیر کپی بگیریم و کپی اونو بدیم به تابع ، این روش میشه call by value ولی اگر بیاییم به تابع آدرس مقادیر اصلی رو بدیم ، چون تابع متغییر هارو از مقادیر اصلی میخونه ، هر تغییری توی تابع روی متغییرا ایجاد بشه مستقیما روی مقادیر اصلی اثر میزاره و این روش میشه call by refrence
پس اگر خود متغیرو پاس بدیم میشه call by value اگر ادرساشونو پاس بدیم میشه call by reference
مثلا ما به صورت پیشفرض مقادیر رو به صورت Call by Value انتقال میدیم :
#include <iostream>
using namespace std;
int sum (int x){
x = 10 + x;
return(x);
}
int main()
{
int x = 5;
cout << "The result of 10 + " << x << " is " << sum(x) << endl;
cout << "Value of x is still " << x;
cin.ignore();
}
--------------------------------------------
The result of 10 + 5 is 15
Value of x is still 5
مثلا اینجا ما یه برنامه داریم که متغییر x رو ک عدد 5 رو پیشفرض در خودش داره و میاییم و به تابع sum پاسش میدیم و با عدد 10 جمع میکنه که میشه 15 ، بعد پارس دادنش دوباره با مقدار x رو چاپ میکنیم و باز میشه 5 ، یعنی مقدار x ای که داخل تابع sum شده 15 یه مقدار کاملا جداییه از x خارج ، درواقع دوتا x داریم که در هر Local Variable حساب میشن و مقادیرشون در تابع های خودشون متفاوته
روش کار ما Call by refrence هست و چون ما شئ داریم ، این شئ ها به دو دسته تقسیم میشن :
Mutable objects یا اشئای قابل تغییر : اگر شئ قابل تغییر باشه ، مقداری که تغییر میکنه خارج از تابع هم قابل دسترسه (list, dict, set)
Immutable objects یا اشیای غیر قابل تغییر: اگر شئ غیر قابل تغییر باشن پس مقداری که تغییر میکنه خارج از تابع قابل دسترس نیست (int, float, complex, string, tuple)
مثال از اشیاء قابل تغییر :
def add_more(list):
list.append(50)
print("Inside Function", list)
mylist = [10,20,30,40]
add_more(mylist)
print("Outside Function:", mylist)
----------------------------------
Inside Function [10, 20, 30, 40, 50]
Outside Function: [10, 20, 30, 40, 50]
در اینجا ما یه لیست داریم که قابل تغییره ، و وقتی ما یه عضو جدید (در اینجا 50) رو اضافه میکنیم به این لیست داخل لیست درون و تابع و بیرون تابع اضافه میشه (درواقع call by refrence کردیم)
ولی اشیاء غیر قابل تغییر :
string = "Hi"
def test(string):
string = "hello"
print("Inside Function:", string)
test(string)
print("Outside Function:", string)
---------------------------------
Inside Function: hello
Outside Function: Hi
در اینجا چون رشته غیر قابل تغییر هست پس ما دو مقدار متفاوت در داخل و خارج تابع داریم (انگار call by value کردیم)
نکته : توی cpp هم میشه این کارو انجام داد ، اما با پوینتر ها ما میتونیم یه call refrence درست کنیم به وسیله پاس دادن پوینتر بعنوان ارگومان به تابع ، بجای فرستادن خود ارگومان
قبلش کمی درباره پوینتر ها توضیح بدم : پوینتر متغییره که میتونه موقعیت مکانی یا مقدار یه متغییر دیگرو در خودش بگیره ، اگر متغییری اینطوریه نوشته بشه :
x = &y;
یعنی مکان متغیرy باید ریخته بشه توی x ولی اگر
x = *y;
اینطوری باشه باید مقدار خود متغیر y ریخته بشه تو x
حالا من به دو طریق با پوینتر ها call by refrence میکنم تو cpp :
#include <iostream>
using namespace std;
void swap(int& x, int& y)
{
int temp;
temp = x;
x = y;
y = temp;
}
int main ()
{
int i, j;
i = 5;
j = 10;
cout << "Before swap i is: " << i << " and j is: " << j <<endl;
swap(i,j);
cout << "After swap i is: " << i << " and j is: " << j;
cin.ignore();
return 0;
}
-------------------------------------------
Before swap i is: 5 and j is: 10
After swap i is: 10 and j is: 5
#include <iostream>
using namespace std;
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
int main ()
{
int i, j;
i = 5;
j = 10;
cout << "Before swap i is: " << i << " and j is: " << j <<endl;
swap(&i,&j);
cout << "After swap i is: " << i << " and j is: " << j;
cin.ignore();
return 0;
}
--------------------------------
Before swap i is: 5 and j is: 10
After swap i is: 10 and j is: 5
خیلی درگیر کدش نمیخوام بشم ولی جفتشون یه کارو میکنن ولی به طور خلاصه علامت & قبل اسم متغییرا یعنی قراره تو یه پوینتر بگیری بجای مقدار ارگومان ، جفتشون اول میان i و j رو پاس میدن به void و x میشه i و y میشه j ، پس x = 5 و y = 10 بعد که داخل تابع void ما کارمونو انجام میدیم ، اول temp میشه مساوی x یعنی temp=5 بعد x=y میشه یعنی مقدار y ریخته میشه تو x که جفتشون میشن 10 ، بعد y=temp میشه که مقدار temp یا همون 5 ریخته میشه تو y که در نهایت y میشه 5 ، یعنی الان x=10 و y=5 شده و از اونجایی ک x=i و y=j بوده پس مقادیرشون بعد رفتن تو تابع توسط پوینترا جابجا شده
مبحث تقریبا سختیه ، یکم کد بزنید و بهش فکر کنید ، اگر سوال داشتید در خدمتم :)
عاشق امنیت و نفوذ ، رد تیم و دوستدار بزن بکش :)
کارشناس تست نفوذ سنجی ، علاقه مند به امنیت تهاجمی و رد تیمینگ | عضو انجمن بین المللی ورزش های رزمی کشور آلمان و دارای احکام بین المللی و داخلی کمربند مشکی در سبک های کیوکوشین ، هاپکیدو ، کیک بوکسینگ و چند تام قهرمانی کشوری
زمان پاسخ گویی روز های شنبه الی چهارشنبه ساعت 9 الی 18
فقط به موضوعات مربوط به محصولات آموزشی و فروش پاسخ داده می شود