محمد حسن پزشکیان
عاشق امنیت و نفوذ ، رد تیم و دوستدار بزن بکش :)

تفاوت بین Call By Refrence و Call By Value چیست؟

در این مطلب میخوایم اول به بررسی تفاوت بین Argument و Parameter بپردازیم بعد تفاوت بین Call By Refrence و Call By Value رو در زبان های برنامه نویسی بررسی کنیم

دوره های شبکه، برنامه نویسی، مجازی سازی، امنیت، نفوذ و ... با برترین های ایران

تفاوت بین آرگومان (Argument) و پارامتر (Parameter) چیست؟

در زبان های برنامه نویسی اگر ما بخوایم یه تابعی رو صدا بزنیم و مقادیری رو بهش بفرستیم چند تا اصطلاح داریم :

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 refrence و اگر مقادیر ارگومان و پارامتر متفاوت باشن میشه call by value ، به زبانی دیگر : اگر ما موقعی که میخوایم مقادیر رو پاس بدیم به تابع ، از مقادیر کپی بگیریم و کپی اونو بدیم به تابع ، این روش میشه  call by value ولی اگر بیاییم به تابع آدرس مقادیر اصلی رو بدیم ، چون تابع متغییر هارو از مقادیر اصلی میخونه ، هر تغییری توی تابع روی متغییرا ایجاد بشه مستقیما روی مقادیر اصلی اثر میزاره و این روش میشه call by refrence

پس اگر خود متغیرو پاس بدیم میشه call by value اگر ادرساشونو پاس بدیم میشه call by reference

تفاوت بین Call By Refrence و Call By Value چیست؟

در زبان ++c

مثلا ما به صورت پیشفرض مقادیر رو به صورت 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 حساب میشن و مقادیرشون در تابع های خودشون متفاوته

یادگیری برنامه نویسی برای متخصصین حوزه کامپیوتر این روزها یک الزام به حساب می آید. از جمله محبوب ترین زبان های برنامه نویسی دنیا می توانیم به زبان برنامه نویسی سی شارپ ، زبان برنامه نویسی جاوا ، زبان برنامه نویسی پایتون ، زبان برنامه نویسی سی پلاس پلاس و زبان برنامه نویسی SQL ( لازمه هر زبان دیگری ) و زبان برنامه نویسی PHP اشاره کنیم.

برای آموزش برنامه نویسی می توانید با خیال راحت در قالب دوره های آموزش برنامه نویسی سایت توسینسو ، آموزش سی شارپ ، آموزش جاوا ، آموزش پایتون ، آموزش جنگو ، آموزش PHP ،  آموزش جاوا اسکریپت ، آموزش برنامه نویسی اندروید ، آموزش SQL و آموزش MySQL را بصورت جامع و حرفه ای آموزش ببینید.

در زبان پایتون

روش کار ما 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 کردیم)

call by refrence در ++c

نکته : توی 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 بوده پس مقادیرشون بعد رفتن تو تابع توسط پوینترا جابجا شده

مبحث تقریبا سختیه ، یکم کد بزنید و بهش فکر کنید ، اگر سوال داشتید در خدمتم :)


محمد حسن پزشکیان
محمد حسن پزشکیان

عاشق امنیت و نفوذ ، رد تیم و دوستدار بزن بکش :)

کارشناس تست نفوذ سنجی ، علاقه مند به امنیت تهاجمی و رد تیمینگ | عضو انجمن بین المللی ورزش های رزمی کشور آلمان و دارای احکام بین المللی و داخلی کمربند مشکی در سبک های کیوکوشین ، هاپکیدو ، کیک بوکسینگ و چند تام قهرمانی کشوری

نظرات