نمایش نتایج 1 تا 5 از 5

نام تاپیک: کاربردهای کلاس های حافظه ( Automatic - Static - Extern - Register )

  1. #1

    Cool کاربردهای کلاس های حافظه ( Automatic - Static - Extern - Register )

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

  2. #2

    نقل قول: کاربردهای کلاس های حافظه ( Automatic - Static - Extern - Register )

    سلام
    سوال شما خیلی کلی هست و مطالب زیادی را در بر می گیره مثل اینکه بپرسید سی پلاس پلاس را برای من توضیح بدید اما اجمالا:
    در C++‎11 یک سری تغییرات در این لیستی که ارائه دادید انجام شده
    مشخص کننده های کلاس حافظه عبارتند از
    register
    static
    thread_local
    extern
    mutable
    به غیر از mutable کار اینها تعیین دو خصوصیت مدت حافظه duration و پیوند linkage هنگام اعلان یک نام می باشد

    مدت حافظه یک چیز حداقل طول عمر بالقوه حافظه مربوط به اون چیز هست که چهار دسته میشه:
    static : با شروع برنامه حافظه به متغیر اختصاص داده میشه و در انتهای برنامه آزاد میشه
    thread: با شروع thread حافظه به متغیر اختصاص داده میشه و در انتهای thread آزاد میشه
    automatic: متغیر تعریف شده در یک بلاک ( مثل متغیرهایی که در یک تابع تعریف می کنیم) البته بدون استفاده از کلمات staticو extern و thread_local
    dynamic: که با استفاده از عملگر new فضا به اون اختصاص داده میشه

    برای اینکه بدونیم linkage یا پیوند چیه بهتره بدونیم یک برنامه از پیوند یا link چند واحد ترجمه ایجاد میشه. منظور از واحد ترجمه کدهای موجود در یک فایل سورس cpp به همراه فایلهایی که در اون include میشه هست
    یک نام دارای linkage هست در صورتی که اگر اون نام در دو یا چند محدوده scope بیاد دقیقا منظورش یک چیز باشه. این چیز می تونه یک آبجکت ، رفرنس، تابع، نوع، تمپلیت، فضای نام یا یک مقدار باشه

    محدوده ها هم مثل محدوده بلاک یا محدوده فضای نام و مثل اینها
    یک نام دارای لینکیج خارجی external هست در صورتی که اگر اون نام در واحد های ترجمه مختلف بیاد و یا در محدوده های مختلف یک واحد ترجمه بیاد منظورش یک چیز باشه

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

    یک نام لینکیج ندارد در صورتی که اگر اون نام در محدوده های مختلف بیاد منظورش یک چیز نباشه. یعنی اون نام فقط در یک محدوده معنا داره

    با این مقدمه توضیح مختصر هر یک از کلاسهای حافظه میشه

    register: برای مدت حافظه AUTOMATIC و نیز پیشنهاد به کامپایلر که متغیر را در رجیستر پردازنده قرار بدهد ( این کلمه در C++‎11 منسوخ شده)
    static: برای مدت حافظه static یا thread و نیز لینکیج داخلی به کار میره
    thread_local: برای مدت حافظه thread به کار میره
    extern: برای مدت حافظه static یا thread و نیز لینکیج خارجی به کار میره
    (البته اینها خیلی خلاصه هست مثلا در بعضی مواقع extern موجب نمیشه لینکیج یک چیز خارجی بشه)
    mutable: ربطی به مدت حافظه و لینکیج نداره و جهت تغییر دادن عضو یک کلاس به کار میره در صورتی که اون کلاس const باشه (توی یک تاپیک توضیح دادم)

    حالا با توجه به نیازتون میتونید از هر یک از این کلمات استفاده کنید
    مطالب خیلی خلاصه گفته شد
    پیشنهاد می کنم ابتدا ین منبع را مطالعه کنید:
    en.cppreference.com/w/cpp/language/storage_duration

    و برای مطالعه جزئیات هم به استاندارد C++‎11 مراجعه کنید
    حداقل سوال خودتون را جزئی تر بپرسید چون خیلی مطلب هست.

  3. #3

    نقل قول: کاربردهای کلاس های حافظه ( Automatic - Static - Extern - Register )

    دوست عزیز rahnema1 ممنونم از جوابتون اما من فقط نمونه کد می خوام که کلاس های حافظه داخلشون استفاده شده باشه .

  4. #4

    نقل قول: کاربردهای کلاس های حافظه ( Automatic - Static - Extern - Register )

    تا مفاهیم را ندانیم مثال عملی فایده ای نداره این مثالها خیلی ساده است جزئیات بیشتر در مورد کاربرد اینها در استاندارد گفته شده
    دو تا فایل درست کنید s1.cpp و s2.cpp
    با این دستور هم کامپایل کنید:
    g++ -std=C++‎11 s2.cpp s1.cpp

    //file s1.cpp
    namespace n1
    {
    extern const int a=5;
    const int c=3;
    }
    //file s2.cpp
    namespace n1
    {
    extern const int a;
    static int b=1;
    const int c=4;
    }
    #include <iostream>
    using namespace std;
    int main()
    {
    int d=5;
    cout<<n1::a<<endl;
    cout<<n1::b<<endl;
    cout<<n1::c<<endl;

    }

    این دوفایل تشکیل دو واحد ترجمه می دهند و با هم لینک میشن تا برنامه ایجاد بشه
    در هر دو فایل متغیر a با کلمه extern اعلان شده به این معنا که لینکیج اون خارجیه
    اما در فایل دوم مقداری به a اختصاص نمی دهیم می بینیم که مقدار 5 چاپ میشه
    اگه در مورد متغیر const از کلمه extern استفاده نشه، لینکیج اون داخلی میشه مثل متغیر c
    همین طور که مشاهده می کنید با از محدوده بلاک (تابع main) قادر هستیم به متغیر موجود در یک محدوده دیگر ( فضای نام n1) دسترسی داشته باشیم در صورتی که لینکیج اون داخلی باشه مثل متغیر b و c
    همچنین می تونیم s1 را به عنوان یک کتابخانه کامپایل کنیم و از اون در s2 به همین صورت استفاده کنیم ( منظورم تاکید روی این نکته است که اینها دو واحد ترجمه مختلف هستند)
    در مورد register گفتم که منسوخ شده و متغیر d مدت حافظه automatic داره و با شروع بلاک شروع شده و با پایان اون از بین میره و چه کلمه register بذاریم چه نذاریم فرقی نمی کنه
    در مورد mutable در این تاپیک توضیح داده شد:
    https://barnamenevis.org/showthread.php?445420
    در مورد thread_local هم اون لینکی که در پست قبل گذاشتم در آخرش مثال زده که اون متغیر در چند thread استفاده میشه

  5. #5

    نقل قول: کاربردهای کلاس های حافظه ( Automatic - Static - Extern - Register )

    دیدم بحث خوبی شروع شده گفتم از طریق یه سری مثال در قالب پرسش و پاسخ یه کم بحث را تکمیل کنم
    البته بیشتر تمرکز روی متغیرها هست. در مورد تابع ها و تمپلیت ها وکلاس و غیره هم مطلب هست که فعلا ازش صرفنظر می کنیم
    سوال: از مطالب بالا یه چیزایی فهمیدم اما معلوم نشد متغیر با مدت حافظه static به چه دردی می خوره؟
    جواب: همون طور که گفتم این متغیر با شروع برنامه شروع و تا پایان برنامه ادامه خواهد داشت همچنین مقدار دهی اولیه این متغیرها یک بار در طول برنامه انجام میشه مثلا مثال زیر را ببیند

    #include <iostream>
    using namespace std;
    void f1()
    {
    static int a=0;
    a++;
    cout<<a<<endl;
    }
    int main()
    {
    f1();
    f1();
    f1();
    return 0;
    }

    متغیر محلی a که لینکیج نداره و مدت حافظه اون هم static هست تنها یکبار مقدار دهی اولیه میشه و دفعات بعدی که تابع f1 صدا زده میشه مقدار دهی اولیه نمیشه و فقط به مقدار اون اضافه میشه

    سوال: منظورت چیه که متغیر محلیه؟
    جواب: متغیریه که در محدوده بلاک اعلان میشه، محلیه. همچنین متغیر عمومی هم داریم. بهتره بدونیم تمام کدهای موجود در یک واحد ترجمه از قبیل تابع main و .. درون یک فضای نام قرار دارند؛ اگرچه ما اون فضای نام را تعریف نمی کنیم. اون «فضای نام عمومی» هست. مثلا متغیرهایی که بعضی وقتها دیده میشه قبل از تابع main قرار دارن جزء متغیر عمومی به حساب میان و از اعضای فضای نام عمومی هستند مثل a1

    int a1=2;
    int main()
    {
    //...
    }


    سوال: آیا اگه بخواهیم مدت حافظه یک متغیر static باشه حتما لازمه کلمه static را قبل از اعلان اون بیاریم؟
    جواب: در مورد متغیرهای محلی لازمه . اما تمام متغیرهایی که محلی نباشن و مدت حافظه اونها dynamic و thread نباشه static هستند. مثل متغیر a1 در مثال بالا که مدت حافظه اون static هست

    سوال: گاهی وقتها دیده میشه یک متغیر عمومی به صورت static تعریف میشه در صورتی که می دونیم که static هست. (مثل متغیر a2 در مثال زیر) پس به کار بردن کلمه static چه ضرورتی داره؟

    static int a2=2;
    int main()
    {
    //...
    }

    جواب: به کار بردن کلمه static باعث میشه که لینکیج اون داخلی بشه چون متغیرهای موجود در یک فضای نام دارای لینکیج خارجی هستند ( به تبعیت از فضای نام در برگیرنده اونها) مگر این موارد که داخلی هستند:
    -متغیری که با کلمه static اعلان بشه
    -متغیری که به صورت const یا constexpr اعلان شده باشه اما این اعلان با کلمه extern همره نباشه و یا قبلا اعلان نشده باشه که اون متغیر دارای لینکیج خارجیه

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

    namespace {
    static int a3=2;
    int a4;
    }

    جواب: آفرین به نکته خیلی خوبی اشاره کردی.
    سوال: یک نکته جالب که از مطالب بالا فهمیدم برای اینکه لینکیج یک متغیر خارجی بشه حتما لازم نیست از کلمه extern استفاده بشه
    جواب: همین طوره. حتی در بعضی موارد اعلان یک متغیر با کلمه extern لزوما باعث نمیشه لینکیج اون خارجی بشه
    سوال: دیگه دارم شاخ در میارم. این دیگه چه صیغه ای یه؟
    جواب: اگه ما داخل محدوده یک بلاک متغیری را با کلمه extern اعلان کنیم و این در صورتی باشه که قبل از اون یک متغیر با همان نام و نوع را اعلان کرده باشیم که دارای لینکیج هم باشه ( بدون لینکیج نباشه)، و متغیر اولی توسط دومی قابل رویت باشه، متغیر دومی ، لینکیج متغیر اولی را دریافت می کنه
    دوباره مثل چند پست قبل دو تا فایل به نام s1.cpp و s2.cpp درست کنید
    در فایل s1 متغیری به نام a5 در فضای نام عمومی تعریف کردیم که خود به خود دارای لینکیج خارجی هست
    در فایل s2 قبل از تابع main متغیر a5 را به صورت static تعریف کردیم که باعث میشه مدت حافظه اون static و لینکیج اون داخلی بشه
    در تابع main متغیر a5 را به صورت extern اعلان کردیم اما چون a5 دومی داره یک a5 دیگه را می بینه که اتفاقا دارای لینکیج هم هست ، بنابراین لینکیج اون را دریافت می کنه و قادر به دسترسی به a5 موجود در فایل s1 نیست و عدد 8 چاپ میشه ( همچنین مدت حافظه a5 دومی هم static میشه)

    //file s1.cpp
    int a5=7;


    //file s2.cpp
    #include <iostream>
    using namespace std;
    static int a5=8;
    int main()
    {
    extern int a5;
    cout<<a5<<endl;
    return 0;
    }

    سوال: دیگه دارم خسته میشم فقط یه سوال ته دلم مونده که اگه نپرسم فکر می کنم بحث ناقص مونده.
    جواب: بفرما این یکی هم بپرس
    سوال: حالا a5 دومی موجود در فایل s2 چه طور می تونه به a5 موجود در فایل s1 دسترسی داشته باشه؟
    جواب: اگه a5 دومی اصلا متغیری به این نام را نبینه یا اینکه متغیری به این نام را ببینه اما متغیر اولی دارای لینکیج نباشه، متغیر دوم دارای لینکیج خارجی میشه و ومی تونه به a5 موجود در فایل s1 دسترسی پیدا کنه
    در مثال زیر در فایل s2 اصلا متغیری با نام a5 ایجاد نمیشه و لینکیج خارجی میشه

    //file s2.cpp
    #include <iostream>
    using namespace std;

    int main()
    {
    extern int a5;
    cout<<a5<<endl;
    return 0;
    }

    اما در موردزیر چون a5 اولی داخل بلاک تعریف شده لینکیج نداره و فقط مدت حافظه اون static هست اما و تا قبل از اینکه به extern برسیم اون a5 هست که قابل دسترسی میشه اما وقتی به extern برسیم a5 دارای لینکیج خارجی میشه و a5 اولی از دسترسی خارج و a5 موجود در فایل s1 قابل دسترسی میشه

    //file s2.cpp
    #include <iostream>
    using namespace std;

    int main()
    {
    static int a5=8;
    {
    cout<<a5<<endl;
    extern int a5;
    cout<<a5<<endl;
    return 0;
    }
    }

    سوال: بحث جالبی بود
    جواب: امیدوارم مفید بوده باشه

تاپیک های مشابه

  1. سوال: تاثیر static بودن کلاس بر حافظه
    نوشته شده توسط cprogram در بخش C#‎‎
    پاسخ: 0
    آخرین پست: یک شنبه 25 مهر 1389, 19:25 عصر
  2. سوال: تعریف عضو کلاس با auto,extern,register
    نوشته شده توسط sia abedi در بخش برنامه نویسی با زبان C و ++C
    پاسخ: 6
    آخرین پست: شنبه 04 مهر 1388, 16:46 عصر
  3. لیست توابع و کلاس های static
    نوشته شده توسط sayan در بخش C#‎‎
    پاسخ: 10
    آخرین پست: چهارشنبه 01 مهر 1388, 07:08 صبح
  4. مشخصات کلاس های جاوا را در کجا بیابیم
    نوشته شده توسط javacaran در بخش برنامه‌نویسی جاوا
    پاسخ: 2
    آخرین پست: جمعه 30 بهمن 1383, 08:30 صبح

برچسب های این تاپیک

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •