PDA

View Full Version : کاربرد عملگر ارجاع(&) به همراه نوع برگشتی



chikar
سه شنبه 08 اردیبهشت 1394, 11:44 صبح
سلام



int& funck(void) {
int m = 9;
return m;}

void main()
{
int value = funck(); //int &value = funck();
}


مگر m بعد از به پایان رسیدن تابع funck از پشته حذف نمی شه، پس value، ارجاع به کجاست؟

hosseinam1370
سه شنبه 08 اردیبهشت 1394, 16:02 عصر
کار هردو کد یکی هست، فقط در برنامه نویسی c++ به روش جدیدتر ، میتوان از کد اولتون هم استفاده کرد ، (کد اول مخصوص سی++).
ولی کد دومتون هم در سی و هم در سی++ قابل استفاده هست.

در هر صورت هردوتا call by refrence هستند ، یعنی به قوله شما ارجاع.



موفق باشید.

chikar
سه شنبه 08 اردیبهشت 1394, 16:09 عصر
سوال اصلی من این هست:
مگر m بعد از به پایان رسیدن تابع funck از پشته در حافظه حذف نمی شه، پس value، ارجاع به کجاست؟

USprojeh
سه شنبه 08 اردیبهشت 1394, 16:20 عصر
خب مگه مرجع m برگشت نمیکنه ؟؟؟؟

USprojeh
سه شنبه 08 اردیبهشت 1394, 16:29 عصر
دومی که مشخصه آدرس رو برگشت میده ! وقتی میخوای آدرس حافظه ی هیپ یک متغیر برگشت کنه اینجوری با استار مینویسن !

chikar
سه شنبه 08 اردیبهشت 1394, 17:10 عصر
مثل که اصلا سوال من رو متوجه نمی شید:
ببینید m در تابع funck پس از فراخوانی تابع درون استک قرار می گیره، زمانی که دستور return انجام میشه،ارجاع رو برمی گردونه و m از استک حذف میشه، حالا من می خوام بدونم این ارجاعی که برگشت داده میشه، ارجاع به چه مکانی از حافظه است با وجود حذف m از استک؟

zero_ox
سه شنبه 08 اردیبهشت 1394, 17:38 عصر
it is not legal to return a reference to local var. This would mean the caller receives a reference to garbage

USprojeh
سه شنبه 08 اردیبهشت 1394, 18:55 عصر
خب ببین دوست عزیز ! توی عمل ببین چه اتفاقی میوفته ! ام از بین میره ! اما اینجا مقدارش بر میگرده ! در حقیقت در عمل اتفاق خاصی نمیوفته ! من اصن تا بحال به این مورد بر نخوردم ! اما برای بازگشت آدرس از اشاره گر استفاده میکنن ! که آدرس متغیر رو بگیرن !

chikar
سه شنبه 08 اردیبهشت 1394, 20:36 عصر
اصلا قانع نشدم و جواب سوالم این نبود! ولی باز هم از همه تشکر
کس دیگه ای نیست، برای راهنمایی؟

hosseinam1370
سه شنبه 08 اردیبهشت 1394, 20:55 عصر
سوال اصلی من این هست:
مگر m بعد از به پایان رسیدن تابع funck از پشته در حافظه حذف نمی شه، پس value، ارجاع به کجاست؟

نه ، مقدار m از بین نمیره ، شاید m نباشه ، ولی مقداری که بهش داده شد ، تو همون آدرس باقی میمونه.

ببینید وقتی که شما میگید int m ، یعنی آقای کامپایلر یه حافظه ی 4 بایتی بردار ، و آدرس اون حافظه رو بده به m (تو همین مایه ها) و وقتی که با یک بلاک یا تابع تموم میشه ، عمر متغییر های داخل تابع مثله m هم به سر میرسه ، یعنی متغییر m وجود نداره که به اون مکان حافظه اشاره کنه ولی اون حافظه ایی که به m اختصاص داده شده بود با همون مقدار هنوز وجود داره ، و چون ما قبلش اون آدرس رو گرفتیم و return کردیم ، و اون حافظه که هگزادسیمال اون عدد رو از قبل ذخیره کرده بود ، هنوز روش چیز جدیدی نوشته نشده ، پس اون مقدار همچنان باقی خواهد ماند.و میشه ازش استفاده کرد.

شما میتونید ، کد زیر رو تو ویژال بنویسید (برای فهم بهتر اینطوری نوشتم) و با f10 کردن ، و از پنجره memory ، مقدار داخلی حافظه m رو بعد از پایان بلاک یا تابع ببینید.

#include "stdafx.h"
#include <iostream>
using namespace std;
int* funck(void) {
int m = 9;
return &m;}

void main()
{

int* valuee = funck(); //int &value = funck();
cout << valuee << endl;
system("pause");

}

chikar
سه شنبه 08 اردیبهشت 1394, 21:13 عصر
نه ، مقدار m از بین نمیره ، شاید m نباشه ، ولی مقداری که بهش داده شد ، تو همون آدرس باقی میمونه.

ببینید وقتی که شما میگید int m ، یعنی آقای کامپایلر یه حافظه ی 4 بایتی بردار ، و آدرس اون حافظه رو بده به m (تو همین مایه ها) و وقتی که با یک بلاک یا تابع تموم میشه ، عمر متغییر های داخل تابع مثله m هم به سر میرسه ، یعنی متغییر m وجود نداره که به اون مکان حافظه اشاره کنه ولی اون حافظه ایی که به m اختصاص داده شده بود با همون مقدار هنوز وجود داره ، و چون ما قبلش اون آدرس رو گرفتیم و return کردیم ، و اون حافظه که هگزادسیمال اون عدد رو از قبل ذخیره کرده بود ، هنوز روش چیز جدیدی نوشته نشده ، پس اون مقدار همچنان باقی خواهد ماند.و میشه ازش استفاده کرد.


[/CPP]

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

اگر آقای rahnema1 (http://barnamenevis.org/member.php?305905-rahnema1) بود، فکر می کنم خیلی خوب می تونست کمک کنه! حیف نیستن...

rahnema1
سه شنبه 08 اردیبهشت 1394, 23:58 عصر
اگر آقای ...

سلام، خواهش می کنم دارم خجالت می کشم :خجالت:
اینها مطالب secret نیست بالاخره ما هم از اینور اونور و از سایر دوستان مطالب را پیدا می کنیم
این دو تااعتباری ندارند:



int& funck(void) {
int m = 9;
return m;}


int* funck(void) {
int m = 9;
return &m;}


چون می خواد ارجاع یا اشاره گر به یک شیء که محلی و موقتی هست برگردونه وقتی می گیم حافظه از بین می ره به معنای این نیست که واقعا از بین می ره چون در این صورت کل کامپیوتر نابود می شد! بلکه منظور اینه که حافظه ای که مثلا توسط یک متغیر رزرو شده بود آزاد میشه تا بقیه برنامه بتونه از اون حافظه استفاده کنن
یعنی بعد از اینکه تابع funck اجرا شد تضمینی نیست که در آدرس m یک متغیر دیگه جایگزین نشه! بعد از اون ممکنه هزار اتفاق در استک بیفته و اون قسمت که سابقا محل m بوده دوباره بازنویسی بشه چون بعد از تمام شدن funck دیگه اون حافظه آزاد شده تا بقیه بتونند استفاده کنند

chikar
چهارشنبه 09 اردیبهشت 1394, 11:04 صبح
سلام، خواهش می کنم ...

نفرمایید، راهنمایی های خوب شما جای تقدیر داره :تشویق: انصافا حتی یه روز هم تو این سایت نباشید, عدم حضورتون لمس میشه ...

پس معملوم شد فضای در اختیار m با محتویاتش در اختیار value قرار می گیره و خود m حذف میشه و گفتید تفاوتی هم بین این روش با استفاده از اشاره گر نیست،درسته؟
حالا یه سوال، استفاده از این روش برای برگردوندن مقادیر که خیلی بهتر هست، چون مثل روش معمولی کپی یک مقدار برگردونده نمی شه و عملا آدرس اون برگشت داده می شه(این روش یه جورایی بر عکس فراخوانی با مقدار و فراخوانی با ارجاع است)، پس چرا این روش متداول نیست و بیشتر از این روش استفاده نمیشه؟؟؟
یه سوال دیگه هم اینکه، این روش رو من فقط در سربارگذاری عملگر ها دیدم، چرا اونجا از این روش استفاده میشه، مگر چه مزیتی در اونجا نسبت به روش معمولی داره؟

rahnema1
چهارشنبه 09 اردیبهشت 1394, 17:42 عصر
انصافا حتی یه روز هم تو این سایت نباشید...

از حسن دیدگاه شما نسبت به خودم ممنونم. :خجالت:
ببینید شما فقط یه طرف قضیه را می بینید. تا سوالی نباشه جواب هم به وجود نمیاد.
ارزش سوال شما هم اگه بیشتر از جواب نباشه کمتر نیست
من خودم خیلی وقتها جواب سوالی که پرسیده شده بلد نبودم که اون سوال مرا واداشته که برم جوابش را پیدا کنم یا اینکه جوابش را میدونستم برای اطمینان بیشتر باز هم به منابع مراجعه کردم
در واقع در مطلبی که یاد گرفتم اون کسی که سوال پرسیده نقش مهمی داشته
اما در عین حال جوابهایی که داده میشه خالی از اشکال نیست و خواهش می کنم اگه اشتباهی باشه تذکر بدید


پس معملوم شد فضای در اختیار m با محتویاتش در اختیار value قرار می گیره و خود m حذف میشه و گفتید تفاوتی هم بین این روش با استفاده از اشاره گر نیست،درسته؟


این روش اشتباهه و نباید چنین کاری انجام بدیم
در این سایت:
http://www.codeproject.com/Articles/13363/An-Insight-to-References-in-C
مطلبی درخصوص درک بهتر ارجاع گفته شده البته این مفهوم فقط جهت تقریب ذهن باید استفاده بشه :
وقتی می نویسیم


int a = 5;
int& ref1 = a;
cout << ref1;

در واقع با کمی اغماض می تونیم ارجاع را به عنوان یک اشاره گر ثابت در نظر بگیریم با این تفاوت که کامپایلر خودش هر جا لازم باشه متوجه قضیه می شه و محتوای آدرس را بر می گردونه، نه اینکه خود آدرس را
int a = 5;
int* const ref1 = &a;
cout << *ref1;

حالا بر می گردیم به مثال خودمون
int* const funck(void) {
int m = 9;
return &m;}

اگه این تابع ینجور استفاده بشه
int &value = funck();
این شکلی می شه

int* const value = funck(); =====> int* const value = &m;
cout << *value;

اما اینجا m متزلزل هست یعنی ممکنه مثلا در ادامه برنامه آدرس m دوباره توسط یک متغیر دیگه استفاده بشه و در اون آدرس نوشته بشه و بدون اینکه ما متوجه بشیم مقدار value هم تغییر پیدا کنه


اگه این تابع ینجور استفاده بشه
int value = funck();
این شکلی می شه

int* const temp = funck(); =====> int* const temp = &m;
int value = *temp;
cout << vlaue;

فرض کنید همزمان یک thread در حال اجرا باشه و در فاصله ای که temp برابر m شده و value بخواد مقدار temp را بگیره بیاد در آدرسی گه m در اون قرار داشته تغییر ایجاد کنه که باز هم می بینیم برنامه متزلزل شد
بالاخره نفهمیدیم مزیت این روش چیه خب به طور خیلی ساده می تونیم اینجور بنویسیم

void funck(int& m)
{
m = 10;
}
int value;
funck(value);

یا اصلا بنویسیم
int value = 10;

در سربارگذاری عملگر هم فایده اش اینه که میتونیم چند تا عملگر را پشت سر هم بنویسیم

class A
{
public:
A& operator<<(int val)
{
cout << val;
return *this;
}
};

A a;
a << 5 << 3 << 6;

chikar
چهارشنبه 09 اردیبهشت 1394, 18:58 عصر
ببینید شما فقط یه طرف قضیه را می بینید...
[/CPP]
عالی بود، :تشویق: خیلی کامل بود / مرسی
من حرفم این هست، نمیگم همه ولی شاید کم هم نباشن کسایی که اطلاعاتشون خوبه، ولی یا جواب نمی دن، یا با لحن بد جواب می دن، یا ناقص جواب می دن، یا میگن مگه خودت سرچ بلد نیستی! ، یا اگه دوباره ازشون سوال بپرسی یه جور جواب می دن که دیگه تاپیک رو ادامه ندی یا...
اگر هم اطلاعات کسی که جواب میده کافی نباشه، ممکن هست یه جواب غلط ولی قانع کننده به تو بده و تو هم متوجه نشی و فکر کنی جوابت رو پیدا کردی!!!
من خودم تا مجبور نشم و تا واقعا مطلبی رو نفهمم تاپیک نمی زنم .
ولی خوشبختانه شما هم اطلاعات قوی دارید و هم مهمتر از اون اخلاق ... کاش می شدید یکی از مدیران بخش
بازم مرسی

chikar
پنج شنبه 10 اردیبهشت 1394, 11:28 صبح
در سربارگذاری عملگر هم فایده اش اینه که میتونیم چند تا عملگر را پشت سر هم بنویسیم

class A
{
public:
A& operator<<(int val)
{
cout << val;
return *this;
}
};

A a;
a << 5 << 3 << 6;


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

rahnema1
پنج شنبه 10 اردیبهشت 1394, 11:42 صبح
شاید مثال کامل و خوبی نزدم. وقتی که اراجاع باشه فقط همون a اولی ایجاد شده ولی وقتی بدون ارجاع باشه مرتبا چند تا شیء A ایجاد میشه و این کار هزینه داره که در زیر حالت اول و دوم را مشاهده می کنید

A a;
(((a << 5) << 1)<< 3);
_______ a
_____________ a
___________________ a


A a;
(((a << 5) << 1)<< 3);
_______ temp a1;
_____________ temp a2;
___________________ temp a3;

chikar
پنج شنبه 10 اردیبهشت 1394, 11:48 صبح
و یه سوال دیگه، اگر از این روش استفاده کنیم، آیا ممکن هست باز جایی ایرادی پیش بیاد؟


const int* test_pointer(int x)
{
x += 8;
std::cout << "\n &x: " << &x <<"\n";
return &x;
}
void main() {
const int* const pointer = test_pointer(3);
}





چون در این روش دیگه حتی اگه یه تابع یا thread دیگه هم بخواد x رو تغییر بده، مقداری که فرستاده شده داخل یه ثابت قرار گرفته و عملا غیر قابل تغییر هست!
این روش چی، توصیه میشه یا نه؟

rahnema1
پنج شنبه 10 اردیبهشت 1394, 11:49 صبح
const int* test_pointer(int x)
{
x += 8;
std::cout << "\n &x: " << &x <<"\n";
return &x;
}
void main() {
const int* pointer = test_pointer(3);
}


اینجا هم طول عمر x با پایان تابع به پایان می رسه چون مقدار با value پاس شده نه با رفرنس

chikar
سه شنبه 15 اردیبهشت 1394, 10:38 صبح
فرض کنید همزمان یک thread در حال اجرا باشه ..


یه سوال ذهنم رو مشغول کرده، البته ببخشید چند روز ازش گذشته! و سوالم یه کم طولانی هم هست!

برای اینکه مطلبم رو بهتر برسونم به جای نوع برگشتی و & از نوع برگشتی و * استفاده کردم، لطف کنید کد ها رو ببینید:

متغیر خصوصی کلاس یعنی p_var با پاک شدن نمونه اش در main اون هم پاک میشه، و من می تونم از مکان اون استفاده کنم (فکر کنید یه thread این حافظه رو، آزاد دیده و می خواد ازش استفاده کنه)، با دستور reinterpret_cast آدرس p_var که از طریق رفرنش در اختیار value قرار گرفته رو درون pm1 می ریزم و با تغییر pm1 مقدار value من که همان ارجاع به مکان p_var بود تغییر می کنه

class myclass
{
int p_var;
public:
myclass(int n = 0) {p_var = n;}

int* my_funck(int x)
{
p_var = x;
return &p_var;
}
};
void main() {

myclass *m = new myclass ;
int *value = m->my_funck(29);
delete m;
myclass *pm1 = reinterpret_cast< myclass* > (value);
*pm1 = 99;
std::cout << "value is: " << *value;
}
value is: 99

حالا سوال من اینجاست که با وجود چنین خطری در از دست دادن داده ها، چرا یه کتابخونه قوی مثل qt اینقدر از این روش برای برگردوندن مقادیرش استفاده می کنه؟
یه سر به کلاس QString از کیوت در این لینک (http://doc.qt.io/qt-5/qstring.html) بزنید، ببینید چند تا متد نوع برگشتی شون با * & هست!!! متد های insert، SetNum و...

اصلا من موندم چطوری تشخیص بدم که بهتره مقادیرم رو به چه روشی برگردونم؟؟؟ تو همون لینک هر متد رو با یه روش برگردونده!!

یه مثال هم از همین QString اینجا می زنم، مقادیری که با ارجاع برگشت داده شده رو، البته بعد از حذف نمونه اش تغییر دادم!


QString *str = new QString("ali");
QString str2 = str->insert(1,"1234");
delete str;
QString &ps = reinterpret_cast< QString& > (str2);
ps = "fff";
qDebug() << "str2 is: " << str2;

str2 is : "fff"



آخه، مگه خطرناک نیست این کار، فکر کنید طرف بخواد تو ادامه برنامه، str2 رو داخل دیتابیس ذخیره کنه و فکر می کنه همون مقادیری که برگشت داده شده، از کلاس QString است، اما غافل از اینکه اون مکان از حافظه الآن در اختیار متغیری مثل ps هست!!!

rahnema1
سه شنبه 15 اردیبهشت 1394, 14:23 عصر
در مورد کد اول
وقتی m را delete می کنیم اولا شیئی که توسط m بهش اشاره می شد تخریب می شه و ثانیا حافظه مربوط به اون آزاد می شه
در نتیجه در این حالت دیگه value به یک اشاره گر به اصطلاح معلق اشاره می کنه که دیگه reinterpret_cast و ... بر اساس اون اشاره گر معلق هست و درست نیست
در مورد کد دوم خب ارجاع یعنی همین. هر کدوم از a یا b تغییر کنه اون یکی هم تغییر می کنه:

#include <iostream>
int main()
{
int a = 88;
int& b = a;
b = 77;
std::cout<< a;
}

chikar
سه شنبه 15 اردیبهشت 1394, 14:51 عصر
در مورد کد دوم خب ارجاع یعنی همین. هر کدوم از a یا b تغییر کنه اون یکی هم تغییر می کنه:

#include <iostream>
int main()
{
int a = 88;
int& b = a;
b = 77;
std::cout<< a;
}


بله درست می فرمایید، ولی شما خودتون این تغییرات رو می دید، تغییرات ناخواسته توسط یه thread رو چی می گید؟ مثلا

مثال دوم رو که زدم ببینید، وقتی str رو من delete می کنم حافظه ای که به این شی اختصاص داده شده بود ، آزاد می شه، ولی str2 هنوز ارجاع به اون مکان حافظه هست، حالا اگه یه thread مثلا از سیستم عامل یا مثل همون ps که نوشتم(فرضا ps مال یه برنامه دیگه است و داره از رم استفاده می کنه) بیاد اون مکان از حافظه رو دستکاری کنه، به طور نا خواسته مقدار str2 من هم تغییر میکنه و من اصلا این رو نمی فهمم و ممکن هست بخوام در خطوط بعدی برنامه این str2 رو داخل دیتابیس بریزم!!!
حالا پس با این وجود چرا این همه کاربرد داره استفاده از ارجاع برای برگرداندن مقادیر؟؟ مثلا در کلاس QString در کیوت که لینکش رو بالا هم گذاشتم؟؟؟در این لینک
(http://doc.qt.io/qt-5/qstring.html)
اصلا من موندم چطوری تشخیص بدم که بهتره مقادیرم رو به چه روشی برگردونم! تو همون لینک هر متد رو با یه روش برگردونده!! آیا قانون خاصی داره؟

rahnema1
سه شنبه 15 اردیبهشت 1394, 20:22 عصر
ببینید کلاس Qstring یک عملگر انتساب کپی داره
QString &operator=(const QString &);
کار str->insert اینه که در str یک تغییر ایجاد کنه و سپس همون str تغییر داده شده را برگردونه
بعد شما با عملگر انتساب کپی می آیید رشته str را کاملا کپی می کنید به داخل str2
وقتی str را delete می کنید str2 سر جای خودش باقی می مونه چون محتوای str داخل اون کپی شده
کاربردش هم مثلا دو تا تابع insert و append را در نظر بگیرید
می تونید متدها را پشت سر هم بنویسید

Qstring str;
Qstring str2 = str.insert(.....).append().insert(....).insert(... .);

تابع insert به طور خلاصه اینطور تعریف شده
Qstring& Qstring::insert(......)
{
//.....
return *this;
}
در اون عبارت پشت سر هم به علت اینکه هر بار ارجاعی از str برگردونده میشه تنها هزینه ای که داره همون هزینه append یا insert هست و دیگه شیء موقتی و عملیات کپی اضافی صورت نمی گیره
اما اگه مثلا insert اینجور تعریف شده بود:

Qstring Qstring::insert(.......)
{
//.....
return *this;
}

هر دفعه بعد از insert یا append یک شیء موقتی از نوع Qstring برگردونnه میشه و عملیاتهای مختلف روی شیء های موقتی انجام می گیره
ضمن اینکه در حالت دوم str فقط یکبار تغییر پیدا می کنه و اون عملیات insert اول هست و دیگه تغییر نمی کنه و هم چنین str2 تمام تغییرات و عملیات ها داخلش اعمال میشه
اما در حالت اول تمام اون عملیات ها هم روی str و هم روی str2انجام می گیره

chikar
چهارشنبه 16 اردیبهشت 1394, 14:20 عصر
ببینید کلاس Qstring یک عملگر انتساب کپی داره
[
اول باید بگم :تشویق: / مرسی
یه سوال به غیر از انتساب کپی و سازنده کپی، عنصر کپی دیگه ای هم تو کلاس داریم؟
در کد زیر مقدار funck از طریق ارجاع برمی گرده و داخل value کپی میشه و هر تغییری که روی مکان m بدند، فرقی به حال value نداره، درسته؟ و انگار یه متغیر یا مقدار معمولی تو value کپی شده؟پرسیدم چون می خوام مطمئن شم!


int& funck(void) {
int m = 9;
return m;}

void main()
{
int value = funck();
}

rahnema1
چهارشنبه 16 اردیبهشت 1394, 19:56 عصر
عنصر کپی تا جایی که می دونم همین دو تا هست

همون طور که در پستهای قبلی گفتم این تابع شما کلا اشتباهه و رفرنس به متغیر محلی بر می گردونه

chikar
چهارشنبه 16 اردیبهشت 1394, 20:30 عصر
همون طور که در پستهای قبلی گفتم این تابع شما کلا اشتباهه و رفرنس به متغیر محلی بر می گردونه

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

int &value = funck();

از این استفاده کردم


int value = funck();

rahnema1
چهارشنبه 16 اردیبهشت 1394, 21:35 عصر
گفتم که این تابع شما برا اساس اون تفسیر خاص به شکل زیر در میاد

int * const funck(void)
{
int m = 9;
return &m;
}

int * const temp = &m;
int value = *temp;

در فاصله بین

int * const temp = &m;

و

int value = *temp;

اگه یک thread داخل آدرسی که قبلا m در اون قرار داشت تغییر ایجاد کنه نتیجه برنامه متزلزل می شه
برنامه را شما اینجور بنویسید درست می شه:

int funck(void) {
int m = 9;
return m;}

chikar
چهارشنبه 16 اردیبهشت 1394, 23:20 عصر
گفتم که این تابع شما برا اساس اون تفسیر خاص به شکل زیر در میاد

گفتید، ولی فکر کنم من خوب درکش نکرده بودم! ببخشید:خجالت:
یه سوال کلی، زمانی که یه متغیر برگشت داده میشه، اول تو یه شی موقت مثل temp ریخته می شه و بعد از برگردوندن کامل به تابع فراخوان این شی موقت هم حذف میشه؟

اگر مقداری که برگشت داده می شه رو استاتیک بگیریم، باز هم مشکلی بوجود میاد؟

//int *p = nullptr;
int& funck(void) {
static int m = 9; // p = new int (9);
return m;}
void main() {
int value = funck();/
}

rahnema1
پنج شنبه 17 اردیبهشت 1394, 13:08 عصر
یه سوال کلی، زمانی که یه متغیر برگشت داده میشه، اول تو یه شی موقت مثل temp ریخته می شه و بعد از برگردوندن کامل به تابع فراخوان این شی موقت هم حذف میشه؟

بستگی به بهینه سازی کامپایلر داره ممکنه اصلا چیزی به اسم temp هم درست نشه و مستقیما تبدیل انجام بگیره ولی ما نباید کد خودمون را بر اساس اینها بنویسیم و حتما باید اصول را رعایت کنیم


اگر مقداری که برگشت داده می شه رو استاتیک بگیریم، باز هم مشکلی بوجود میاد؟

استاتیک مشکلی نداره چون متغیر استاتیک تا پایان برنامه در حافظه خواهد بود و مثل متغیر محلی نیست که با تمام شدن تابع طول عمرش تموم بشه