PDA

View Full Version : سوال: تفاوت متغیر و شی



forodo
یک شنبه 25 آبان 1393, 19:47 عصر
سلام
من مباحث شی گرایی رو داشتم می خوندم و توی قسمت Value Type و Reference Type گفته بود که در Reference Type ها متغیر در حافظه stack ذخیره می شه و شی در حافظه Heap ذخیره میشه.
یعنی:
class c1 = new class();
stack ----- heap
c1(ref) ----- c1
الان من متوجه نمی شم که این یعنی چی.
همه چی رو باهم قاطی کردم.

esafb52
یک شنبه 25 آبان 1393, 19:59 عصر
با سلام دوست عزیز حافظه استک خیلی کم هست و ظرفیت زیادی نداره به همین خاطر اشیایی که حجمشون زیادتره در هیپ نگه داری میشن و اشیا کوچکتر در استکو کلی داستان دیگه مثل باکس و آنباکس و........ یعنی مثلا وقتی یه متغییر از جنس int تعریف میکنی مقدارش در استک نگه داری میشه ولی اگر خاصه یه کلاس تعریف کنی در هیپ ساخته میشه کلا هرچی استراکت هست در استک ساخته میشن و رفتارهای خاصی دارن و لی دلیگیت و کلاس ها و اینترفیس ها و استرینگ ها جز رفرنس تایپ ها هستن رفتارهشون هم متفاوته و.....

forodo
یک شنبه 25 آبان 1393, 20:32 عصر
الان توی خط پایین متغیر کدومه و شی کدومه؟:
class c1 = new class();

esafb52
دوشنبه 26 آبان 1393, 09:48 صبح
الان توی خط پایین متغیر کدومه و شی کدومه؟:
class c1 = new class();
با سلام الان اون C1 رو سیستم در قسمت استک میسازه فکر کنم بهش بگن پوینتر ولی شی کی بعد از دستور NEW اومده(class();) در هیپ ساخته میشه و سیستم از طریق اون اشاره گر به اون دسترسی داره

rahnema1
دوشنبه 26 آبان 1393, 10:26 صبح
نوع یا type نحوه نمایش مقادیرداده ها و عملیاتی که روی اون مقادیر قابل انجام هست را بیان می کنه. مثلا نوع byte برای خودش مقادیر مجاز بین 0 تا 255 تعریف می کنه و عملیاتهای مجاز بر روی byte هم مثل عملیات جمع و تفریق و... هست.
متغیر یا variable ظرفی برای نگهداری داده ها هست.باید برای هر متغیر یک type مشخص کنیم.
برای توضیح object می تونیم از دو گونه type نام ببریم
value type که در این حالت، متغیر یا variable ، دربرگیرنده یک مقدار اجازه داده شده توسط نوع هست
reference type در این حالت، متغیر یا variable، دربرگیرنده آدرس ( ارجاع) مقدار اجازه داده شده توسط نوع هست
value type ها مثل byte یا int یا struct یا ...
reference type ها مثل string یا class یا ...
object ها مرتبط میشن با reference type ها
مثلا در مثال زیر یک variable تعریف کردیم به نام b از نوع byte که داده ای به مقدار 25 را در اون ذخیره میشه. به عبارت دیگه b ظرفی هست که مقدار 25 در اون قرار می گیره یعنی اگه با استفاده از b قادر خواهیم بود مستقیما به 25 دسترسی پیدا کنیم

byte b = 25;
string s = "Hello";

اما در مورد بعدی یک متغیر به نام s تعریف کردیم از نوع string که آدرس داده ای به مقدار "Hello" در اون ذخیره میشه. به عبارت دیگه یک ظرف در یک جا ( غیر از s ) ایجاد میشه و مقدار "Hello" و ( یک سری چیزهای دیگه) در اون قرار می گیره و فقط آدرس اونجا در s ذخیره میشه. در اینجا با استفاده از s به Hello مستقیما دسترسی پیدا نمیشه بلکه ابتدا به آدرس مراجعه شده و مقدار موجود در آدرس بهش دسترسی پیدا میشه (دسترسی غیر مستقیم)
حالا object چیه؟ همونیه که در یک ظرف دیگه ریخته شده بود و ما قادر هستیم توسط آدرس اون بهش دسترسی داشته باشیم
variable چیه؟ همون s و b
یا در مثال زیر

struct Point1
{
public int x;
public Point1(int _x)
{
this.x = _x;
};
}

class Point2
{
public int x;
public Point2(int _x)
{
this.x = _x;
};
}

Point1 p1 = new Point1(3);
Point2 p2 = new Point2(5);

در مورد اول variable داریم به نام p1 از نوع struct که مقدار 3 در اون ذخیره میشه
اما در مورد دوم variable داریم به نام p2 از نوع class . عدد 5 در یک جای حافظه ذخیره میشه همچنین به همراه 5 اطلاعاتی در خصوص نوع Point2 و یک ID در اونجا ذخیره میشه سپس آدرس اونجا در p2 ذخیره میشه. در اینجا object میشه عدد 5 و اطلاعات اضافی دیگه یعنی object میشه محتوای آدرسی که توسط p2 به اون اشاره شده
علت اینکه در مورد اول object نداشتیم این بود که struct از گونه value type هست و آدرس ایجاد نمیکنه و مستقیما مقدار مورد نظر در متغیر ذخیره میشه برعکس class که reference type هست

Milad.PJ
دوشنبه 26 آبان 1393, 11:08 صبح
با سلام الان اون C1 رو سیستم در قسمت استک میسازه فکر کنم بهش بگن پوینتر ولی شی کی بعد از دستور NEW اومده(class();) در هیپ ساخته میشه و سیستم از طریق اون اشاره گر به اون دسترسی داره

با سلام
C1 یک نمونه از شی Class هست و تا زمانی New نشده باشه هنوز براش حافظه ای در نظر گرفته نمی شه !
مثلا :


Class C1;

این حافظه ای از هیپ اشغال نمی کنه (شاید فقط از استک حافظه اشغال کنه). اما:


C1 = new class();

این باعث می شه برای C1 که یک نوع ارجاعی هست ، براش حافظه در نظر گرفته بشه تا زمانی Disposeبشه .

تو یک منبع خود مایکروسافت خوندم بعد از Dispose باید (در اینجا) C1 در انتها برابر با null بشه تا اشاره گر هم از بین بره ! یعنی ابتدا Dispose تا فضای اشغال شده در اصطلاح خالی بشه و در نهایت null تا اشاره گر به اون فضا نیز از بین بره !


C1.Dispose();
C1 = null;

rasoolf
دوشنبه 26 آبان 1393, 11:27 صبح
من نفهمیدم شما با فرق بین متغیر و شی مشکل داری یا با فرق بین value type و reference type.

forodo
دوشنبه 26 آبان 1393, 13:04 عصر
نوع یا type نحوه نمایش مقادیرداده ها و عملیاتی که روی اون مقادیر قابل انجام هست را بیان می کنه. مثلا نوع byte برای خودش مقادیر مجاز بین 0 تا 255 تعریف می کنه و عملیاتهای مجاز بر روی byte هم مثل عملیات جمع و تفریق و... هست.
متغیر یا variable ظرفی برای نگهداری داده ها هست.باید برای هر متغیر یک type مشخص کنیم.
برای توضیح object می تونیم از دو گونه type نام ببریم
value type که در این حالت، متغیر یا variable ، دربرگیرنده یک مقدار اجازه داده شده توسط نوع هست
reference type در این حالت، متغیر یا variable، دربرگیرنده آدرس ( ارجاع) مقدار اجازه داده شده توسط نوع هست
value type ها مثل byte یا int یا struct یا ...
reference type ها مثل string یا class یا ...
object ها مرتبط میشن با reference type ها
مثلا در مثال زیر یک variable تعریف کردیم به نام b از نوع byte که داده ای به مقدار 25 را در اون ذخیره میشه. به عبارت دیگه b ظرفی هست که مقدار 25 در اون قرار می گیره یعنی اگه با استفاده از b قادر خواهیم بود مستقیما به 25 دسترسی پیدا کنیم

byte b = 25;
string s = "Hello";

اما در مورد بعدی یک متغیر به نام s تعریف کردیم از نوع string که آدرس داده ای به مقدار "Hello" در اون ذخیره میشه. به عبارت دیگه یک ظرف در یک جا ( غیر از s ) ایجاد میشه و مقدار "Hello" و ( یک سری چیزهای دیگه) در اون قرار می گیره و فقط آدرس اونجا در s ذخیره میشه. در اینجا با استفاده از s به Hello مستقیما دسترسی پیدا نمیشه بلکه ابتدا به آدرس مراجعه شده و مقدار موجود در آدرس بهش دسترسی پیدا میشه (دسترسی غیر مستقیم)
حالا object چیه؟ همونیه که در یک ظرف دیگه ریخته شده بود و ما قادر هستیم توسط آدرس اون بهش دسترسی داشته باشیم
variable چیه؟ همون s و b
یا در مثال زیر

struct Point1
{
public int x;
public Point1(int _x)
{
this.x = _x;
};
}

class Point2
{
public int x;
public Point2(int _x)
{
this.x = _x;
};
}

Point1 p1 = new Point1(3);
Point2 p2 = new Point2(5);

در مورد اول variable داریم به نام p1 از نوع struct که مقدار 3 در اون ذخیره میشه
اما در مورد دوم variable داریم به نام p2 از نوع class . عدد 5 در یک جای حافظه ذخیره میشه همچنین به همراه 5 اطلاعاتی در خصوص نوع Point2 و یک ID در اونجا ذخیره میشه سپس آدرس اونجا در p2 ذخیره میشه. در اینجا object میشه عدد 5 و اطلاعات اضافی دیگه یعنی object میشه محتوای آدرسی که توسط p2 به اون اشاره شده
علت اینکه در مورد اول object نداشتیم این بود که struct از گونه value type هست و آدرس ایجاد نمیکنه و مستقیما مقدار مورد نظر در متغیر ذخیره میشه برعکس class که reference type هست

با سلام
C1 یک نمونه از شی Class هست و تا زمانی New نشده باشه هنوز براش حافظه ای در نظر گرفته نمی شه !
مثلا :


Class C1;

این حافظه ای از هیپ اشغال نمی کنه (شاید فقط از استک حافظه اشغال کنه). اما:


C1 = new class();

این باعث می شه برای C1 که یک نوع ارجاعی هست ، براش حافظه در نظر گرفته بشه تا زمانی Disposeبشه .

تو یک منبع خود مایکروسافت خوندم بعد از Dispose باید (در اینجا) C1 در انتها برابر با null بشه تا اشاره گر هم از بین بره ! یعنی ابتدا Dispose تا فضای اشغال شده در اصطلاح خالی بشه و در نهایت null تا اشاره گر به اون فضا نیز از بین بره !


C1.Dispose();
C1 = null;
با تشکر از دوستان
پس یعنی اگر ما بنویسیم:
class ali;
اینجا ali متغیر هستش ولی اگر بنویسیم:
ali = new class();
اینجا ali شی هستش.

من نفهمیدم شما با فرق بین متغیر و شی مشکل داری یا با فرق بین value type و reference type.
می دونم خیلی سوالم سطح پایینه ولی آدم بعضی مواقع هنگ می کنه وقتی داره در مورد یه مطلب جدید مطالعه می کنه.
فرق بین Value Type و Reference Type رو می دونم حتی اگر اشتباه نکنم در Value Type بدون دستکاری کپی ارسال می شه و تغییرات روی کپی انجام می شه ولی در Reference Type خود شی ارسال می شه و با اعمال تغییرات مقدار اصلی هم تغییر می کنه.

مهرداد صفا
دوشنبه 26 آبان 1393, 16:35 عصر
با تشکر از دوستان
پس یعنی اگر ما بنویسیم:
class ali;
اینجا ali متغیر هستش ولی اگر بنویسیم:
ali = new class();
اینجا ali شی هستش.

سلام.
خیر. در دو حالت ali متغیر هست، متغیری از نوع Class که در حالت اول به هیچ آبجکتی اشاره نمیکنه و مقدارش null هست؛ در حالیکه در حالت دوم با دستور new یک شی از نوع Class در heap ساخته میشه و میشه گفت آدرسش در stack و در متغیر ali ذخیره میشه.
به دفعات پیش میاد که یک شی داشته باشیم و چند تا متغیر. به عنوان مثال اگر بگیم:


//1:
X c=new X();
X a=c;
X b=c;
در واقع a و b و c سه متغیر هستند که به یک شی اشاره می کنند؛ در همین حالت اگر بگیم:


//2:
X d=new X();
c=d;
متغییر c تغییر کرده اما b و a کماکان به همون شی قبلی اشاره می کنند، چرا که آدرس یک شی جدید به c داده شده؛ و اگر بگیم:


//3:
a.y=newvalue
مقدار b.y هم به newvalue تغییر میکنه، به دلیل اینکه اینجا ما خصوصیت آبجکتی رو تغییر دادیم که در دو متغیر b و a وجود داشت، واضحه که این تغییر در c اعمال نمیشه، به دلیل اینکه به c با عملوند (=) یک مقدار/آدرس جدید دادیم.
از طرفی ممکنه آبجکتی داشته باشیم که هیچ متغیر/اشاره گری براش وجود نداشته باشه:



(new SoundPlayer(@"c:\windows\media\chimes.wav")).Play();
که البته این مورد در اولین فرصت توسط GC حذف خواهد شد.
در آخر فراموش نکنید تمام این موارد به reference type ها بر میگرده و حساب value type ها جداست.

Milad.PJ
دوشنبه 26 آبان 1393, 22:44 عصر
سلام مجدد
ایراد بزرگی که به نظر من می رسه ، اصل مقایسه بین متغیر و شی هست ! چون این دو از یک جنس نیستند ! ما اصطلاحا باید بگیم دو نوع متغیر داریم یکی نوع مقداری و یک نوع ارجاعی (یا همون اشاره گر) ، که :
1.در متغیر مقداری ، مستقیما محتوای مورد نظر ذخیره می شه
2.در متغیر ارجاعی ، "آدرس" محتوای مورد نظر

اما بحث شی کلا جداست . در واقع شی یک تعریف هستش (شاید شبیه یک نوع داده ای) و به خودی خود در زمان اجرا هیچ حافظه ای اشغال نمی کنه تا زمانی که ما یک نمونه از اون شی رو new کنیم ! وقتی که ایجاد شد ، براش حافظه در نظر گرفته می شه و توسط یک متغیر از نوع ارجاعی به اون قسمت از حافظه اشاره می شه که در درون خود این متغیر فقط آدرس محتوای "نمونه ای" که از اون شی ایجاد کردیم قرار می گیره !

مثلا int A ، در اینجا خود int هیچ جا حافظه نمی گیره (چون تعریف یک بازه عددی هست و تعریفش هم روی هارد دیسک!) ولی برا ی A حافظه در نظر گرفته می شه تا در اون محتوای مناسب و مورد نظر رو بریزیم ! درست شبیه class C برای خود کلاس حافظه در نظر گرفته نمی شه اما برای C که در واقع اشاره گر هست فعلا مقدار null ذخیره می شه (که C یک نمونه از Class هست) !
حالا اگر بگیم :


class c = new class();

الان در حافظه فضایی در نظر گرفته می شه با توجه به اندازه و نوع مقادیری که توسط تابع سازند class معرفی می شه !
و در داخل متغیر C ( که متغیری از نوع ارجاعی یا همان اشاره گرمیباشد ) فقط آدرس حافظه محتوای کلاس ذخیره می شه !

از اساتید خواهش می کنم اگر جایی رو اشتباه کردم اصلاح بفرمایند !!!