رفتن به مطلب
جامعه‌ی برنامه‌نویسان مُدرن ایران

قاسم رمضانی منش

میانجی گر‌ها
  • تعداد ارسال ها

    41
  • تاریخ عضویت

  • آخرین بازدید

  • روز های برد

    4

آخرین بار برد قاسم رمضانی منش در 8 فروردین

قاسم رمضانی منش یکی از رکورد داران بیشترین تعداد پسند مطالب است !

اعتبار در سایت

22 عالی

درباره قاسم رمضانی منش

کاربـــر رسمی
  • تاریخ تولد 9 آذر 1378

اطلاعات شبکه‌ای

موقعیت

  • شهر
    Esfahan

آخرین بازدید کنندگان نمایه

335 بازدید کننده نمایه
  1. قاسم رمضانی منش

    سلام ؛ Container : این اسامی‌ای که اسم بردید. تماماً Continer هستند. و وظیفه نگه‌داری داده‌هارا دارند. برای اینکه برنامه‌نویس دستش باز باشه در مدیریت داده‌ها در زبان برنامه‌نویسی سی‌پلاس‌پلاس می‌تونید از این کانتینرها در جهت نگه‌داری داده‌هاتون استفاده کنید. که استفاده از توابع و کلاس‌های موجود در هدرفایل algorithm در کنار این کانتینرها پیشنهاد میشود و می‌تواند قدرت کنترل بیشتری به برنامه‌نویسی بر روی داده‌های خود بدهد. که خود بسیار در پرفورمنس (به انگلیسی : performance) برنامه تاثیر دارد. Qt Container : از آن‌جایی که Qt یک فریمورک هست. برای اینکه برنامه‌نویسی به راحتی بتواند با کلاس‌ها و توابع این فریمورک تعامل برقرار کند ؛ Qt یک‌سری از مخازن (معادل فارسی کانتینر) را بازنویسی کرده‌است. که می‌توانید در این لینک بیشتر در این‌‌باره مطالعه کنید.
  2. قاسم رمضانی منش

    علیکم‌السلام ؛ قبل از اینکه به پاسخ مستقیم سؤال بپردازیم ، بیاید درک کنیم چه شد که template ها نیاز برنامه‌نویس شد. این تابع را در نظر بگیر : int Sum (const int& first, const int& second){ return first+second; } این تابع دو عدد از نوع int دریافت و حاصل جمع‌شون را بر می‌گردونه. خب ! حالا چه میشه اگه شما بخواید به جای int نوع double ارسال کنید ؟ و برنامه‌ی شما با انواع مختلفی داده نیاز داشته باشه که با این تابع کار کنه. شاید بگید خب یک تابع دیگه با پارامتر و نوع بازگشتی double می‌نویسم. با این روش چه مشکلاتی پیش می‌آید : کد تکراری. بالا رفتن درصد خطای کد. افزایش بی‌دلیل حجم کد. سخت شدن مدیریت کد. مشکل در آپدیت کردن سورس کد. و ... زبان سی‌پلاس‌پلاس برای رفع این مشکل‌ما template ها را معرفی کرده است. template ها می‌توانند هر نوع داده‌ای را قبول کنن. تابع زیر ، تابع template بازنویسی شده‌ی تابع Sum است که در مثال بالا نوشتیم : template <typename newType> newType Sum (const newType& first, const newType& second){ return first + second; } خییییلی بزرگ شد ن ؟. خب می‌تونیم کوتاهش کنیم : template <typename newType> newType Sum (const newType& first, const newType& second){ return first + second; } نکته : می‌دانیم که کامپایلر فاصله‌هارا نادیده می‌گیره. خب ! اوّل برای تبدیل تابع ، به یک تابع template باید از کلمه‌ی کلیدی template استفاده کنیم. و بعد با استفاده از < > اسم نوع داده‌های جدیدمان را بنویسیم. نکته : ما هیچ نوع داده‌ی جدیدی درواقع تعریف نمی‌کنیم. این تعریف فقط معرفی یک اسم به عنوان نوع داده‌ای هست که می‌تواند به هر چیزی اعم از int,double ,... تبدیل بشود. و داخل < > ما از کلمه‌ی‌کلیدی typename برای تعریف اسم داده‌‌ استفاده کردیم. و همچنین می‌توانیم کلمه‌ی‌کلیدی class نیز استفاده کنیم که هردو برابر یک دیگر هستن. امّا زمانی شما دارید templateی از template درست می‌کنید. مثلاً این نمونه : template < template <typename> class MyTmpClass, typename newType> اینجا دیگه نمی‌توانید بین کلمه‌کلیدی typename و class تفاوت قائع نشید. چرا که نیازه صراحتاً مشخص. امّا در استاندارد ۱۷ این مشکل وجود ندارد ِ؛ ولی بهتر است که این تفاوت را اعمال کنیم. حال به راحتی می‌توانیم تابع را فراخوانی کنیم. به تکه کدزیر توجه کنید Sum (12 ,32); Sum (1'000'000'000'000,3212'333'233); Sum (std::string("ghasem") , std::string("ramezani")); Sum (12, 32.0); سه خط اوّل کد بدون مشکل کامپایل می‌شوند. الا خط ‌آخری. چرا که ما یک پارامتر با نوع int و یک پارامتر با نوع double‌ ارسال کردیم. برای حل این مشکل بیاید ببینیم که template ها به چه صورت کار می‌کنند. فرض کنید این تابع را فراخوانی کردیم : Sum ( int , int ); وقتی کامپایلر به این تابع بر می‌خورد. تابع template مارا به این‌صورت برای ما بازنویسی می‌کند : int Sum (const int& first, const int& second){ return first + second; } خب ! و وقتیما سعی می‌کنیم این تابع را فراخوانی کنیم : Sum ( int , double ); برنامه کامپایل نمی‌شود و خطای زیر را ساطع میکنن. چرا که یک پارامتر Int و دیگری double هست. ./main.cpp:5: candidate template ignored: deduced conflicting types for parameter 'newType' ('int' vs. 'double') آیا این شکل استفاده از توابع براتون آشنا نیست ؟ یه کم فک کنید : std::vector std::array std::list تمام این کلاس‌ها ، template class هستند. و هر نوعی می‌توانند قبول کنند : #include <vector> #include <string> class myClass{ public: myClass(){} }; int main (void){ std::vector <int> myIntger {1,2,3,4}; std::vector <std::string> myString {"ghasem" , "ramezani"}; std::vector <myClass> myClassVector; return 0; } نکته : این توضیح خیلی خلاصه از template ها و روش استفاده از آنها بود و به همین دو خط محدود نمی‌شوند. و اینکه گفتید "به نظر پیچیده می‌باشد" . پیچیدگی در عین سادگی یکی از قابلیت‌های فوق‌العاده‌ی زبان سی‌پلاس‌پلاسه. اصلاً کد باید وحشت‌ناک باشه.
  3. قاسم رمضانی منش

    چگونه کد خود را زیبا کنیم؟

    با سلام. در این مقاله قصد بر معرفی چند ابزار کاربردی برای برنامه‌نویسان گرامی را داریم. پس با ما همراه باشید. |Carbon| قبل از هر چیزی کمی به کد زیر نگاه کنید : #include <KWayland/Server/output_interface.h> #include <KWayland/Server/outputdevice_interface.h> namespace KWayland { namespace Server { class OutputInterface; class OutputDeviceInterface; class OutputChangeSet; class OutputManagementInterface; class XdgOutputInterface; } } namespace KWin { namespace ColorCorrect { struct GammaRamp; } آیا شما واقعاً رغبت به خواندن این کد می‌کنید ؟ صد در صد خیر. چرا که هیچ indent یا code highlight در نظر گرفته نشده‌اس ! در نظر بگیرید اگر ۱۰۰۰ خط کد بود . در اینجا وب‌سایت Carbon به ما اجازه قالب‌بندی ، تغییر فونت ، رنگ‌بندی و... کدهارا میدهد. Carbon تعداد زیادی از زبان‌های برنامه‌نویسی را اعم از C\C++ , Python , JS ,... پشتیبانی میکند. برای شخصی‌سازی تم مورد علاقه خود. کافی است که تنظیمات خود را اعمال و بعد url سایت را ذخیره کنید.این یک نمونه از تنظیماتی است که بنده اعمال کردم : حال به راحتی می‌توانید با اسکرین گرفتن از کدزیبای خود آن را برای دوستان خود ارسال کنید. |Beautify Tools| سایت Beautify Tools مجموعه‌ای عظیم ابزارهایی اعم از : Beautifiers And Minifiers Converters String Utilities CSS Preprocessors Utilities Unit Converters Cryptography ... می‌باشد. که بسیار به کمک برنامه‌نویسان وب می‌آید. برای مثال شما یک فایل حجیم CSS دارید. که برای راحتی و قابل‌خواندن‌بودن کد از indent های بسیار استفاده کرده‌اید که خود باعث بالا بردن حجم نهایی فایل شده‌اند. به راحتی با استفاده از ابزار CSS Beautifier می‌توانید تمام indent های بی‌مصرف را از بین ببرید : |Artistic Style| Artistic Style یک ابزار فرم‌دهنده (indenter) برای زبان‌های C, C++, C++/CLI, Objective‑C, C#, and Java می‌باشد. برای نصب و استفاده به مستندات نصب این ابزار مراجعه کنید. |Clang Format| Clang Format یک ابزار command-line بسیار قدرتمند برای مرتب کردن ، قالب‌بندی و... کد منبع می‌باشد : ابزار Clang Format فقط به Command Line محدود نمی‌شود. شما می‌توانید به راحتی با IDE مورد علاقه خود این ابزار را تطبیق بدهید. مثل : Vim Qt Creator Visual Studio BBEdit ... برای استفاده به سایت مرجع مراجعه کنید. موفق‌‌ و پیروز باشید.
  4. قاسم رمضانی منش

    با سلام. در نسخه‌های قدیمی Qt Creator امکان این وجود داشت ما به راحتی از کلاس‌هایی مانند QThread ارث‌بری کنیم. اما این قابلیت داخل نسخه جدید Qt Creator محدود به چند کلاس خاص اعم از QObject , QWidget , ... شده است. آیا روشی برای شخصی‌سازی این کلاس‌ها میباشد ؟
  5. با سلام. با توجه به اینکه محیط Qt Creator برای استفاده از QWidget یا Qt Quick یک محیط‌بصری هم تعبیه کرده است که کار را برای استفاده راحت‌تر کرده است. امّا واقعاً استفاده از این ابزار در پروژه‌های بزرگ درست می‌باشد ؟ یا اینکه باید از برای کنترل بیشتر با استفاده از کدنویسی‌محض طراحی‌محیط را به عهده گرفت ؟ در این‌صورت ... وظیفه‌ی اصلی این محیط طراحی چیست ؟ - مثال‌هایی که خود Qt هم دارد ، بدون استفاده از محیط ویژوال طراحی شده است.
  6. قاسم رمضانی منش

    مرسی از توضیحاتتون. بله اطلاع از کراس‌پلتفرم شدن MS SQL Server دارم... ولی خب مایکروسافت است دیگر ... . درمورد نیاز واقعی هم گفتم که برنامه حسابداری یه موسسهٔ آموزشی هست که فقط نیاز به ذخیره اطلاعات متنی هست... . این برنامه کلاینت هست و روی دسکتاپ و موبایل قرار خروجی گرفته بشه. که دیتابیس هم داخل سرور هست. و همزمان ممکنه حداکثر ده کاربر به دیتابیس دسترسی داشته‌باشن. و با توجه به توضیحات اطلاعات پردازشی سنگین نداریم.
  7. با سلام. معیار‌ها برای انتخاب یک دیتابیس برای یک برنامه‌ی حسابداری چه چیزهایی میتواند باشد ؟ بنده درحال شروع نوشتن یک برنامه‌ی حسابداری با استفاده از فریمورک Qt هستم. و وهله اوّل که درحال طراحی بخش‌های مختلف برنامه هستم نیاز به انتخاب یک دیتابیس دارم. که با وجود تنوع دیتابیس‌ها در این زمینه نیاز دانستم که نظر مابقی دوستان را در این زمینه بدانم. بنده برنامه‌‌ی حسابداری هلو را دیدم که از دیتابیس MS SQL Server استفاده میکند. ولی خب برنامه‌ی من Cross-Platform می‌باشد و نمیتوانم از MS SQL Server استفاده کنم.
  8. قاسم رمضانی منش

    درست متوجه منظورتون نشدم ! ولی : void Dialog::on_pushButton_2_clicked(){ mThread->Stop = false; } این اسلات (slot) وقتی صدا زده میشه خب باید مقدار متغیر MyThread::Stop رو برابر false قرار بده دیگه ! درسته ؟ و طبق دستوراتی که داخل تابع void MyThread::run نوشته شده : درصورتی‌که این متغیر مقدارش false باشه باید حلقه شکسته بشه و دیگه چیزی emit نکنه. و وقتی ما این اسلات را فراخوانی میکنیم. اتفاقی نمی‌افته و باز حلقه به کار خودش ادامه میده.
  9. با سلام. در حال یادگیرQt و Thread ها بودم که به مشکل دسترسی به متغیر در Thread بر خوردم. کلاس زیر از QThread مشتق شده است : #ifndef MYTHREAD_H #define MYTHREAD_H #include <QObject> #include <QWidget> #include <QThread> #include <QMutex> class MyThread : public QThread { Q_OBJECT public: explicit MyThread(QObject *parent = nullptr); void run() override; bool Stop; signals: void NumberChanged(int); }; #endif // MYTHREAD_H #include "mythread.h" MyThread::MyThread(QObject *parent) : QThread (parent) { } void MyThread::run() { for(int i=0; i<100000000 ; ++i){ QMutex mutex; mutex.lock(); if (this->Stop) break; mutex.unlock(); emit NumberChanged(i); this->msleep(100); } } داخل فرم خودم دو QPushBotton و یک QLabel دارم. که یکی از دکمه‌ها (QPushButton) وظیفه اجرای یک QThread را دارد و یکی دیگه باعث متوقف کردن کار QThread ایجاد شده : #include "dialog.h" #include "ui_dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog){ ui->setupUi(this); mThread = new MyThread(this); connect(mThread,SIGNAL(NumberChanged(int)),this,SLOT(onNumberChanged (int))); } Dialog::~Dialog(){ delete ui; } void Dialog::onNumberChanged(int Number){ ui->label->setText(QString::number(Number)); } void Dialog::on_pushButton_clicked(){ mThread->start(); } void Dialog::on_pushButton_2_clicked(){ mThread->Stop = false; } در کد بالا زمانی‌که on_pushButton_clicked فراخوانی شد. QThread را اجرا میکند. و در مقابل زمانی‌که on_pushButton_2_clicked فراخوانی شد. متغیر bool MyThread::Stop را برابر مقدار false میگذارد که باعث از بین رفتن عملیات QThread ایجاد شده میشود. اما در اصل هیچ تفاوتی ایجاد نمیکند ؟ و زمان بستن برنامه با خطای لاگ زیر برخورد میکنم : 21:39:20: Starting /tmp/untitled/build-untitled-Desktop_Clang_7_0_0-Debug/untitled... QThread: Destroyed while thread is still running 21:39:32: The program has unexpectedly finished. 21:39:32: The process was ended forcefully. 21:39:32: /tmp/untitled/build-untitled-Desktop_Clang_7_0_0-Debug/untitled crashed. کجای کار اشتباه شده است ؟
  10. با سلام. به چه روشی میتوان خروجی متن را در لحظه آپدیت کرد. برای مثال کد زیر را در نظر داشته باشید : #include <iostream> int main (void){ for(unsigned int index =10 ; index <= 100 ; index+=10) std::cout << index << '%' << std::endl; return 0; } که خروجی زیر تولید میشه : [ghasem@clibcore AnotherJustForTest]$ g++ -o main main.cpp && ./main 10% 20% 30% 40% 50% 60% 70% 80% 90% 100% خب ! حالا اگر ما بخواهیم همان خط اول فقط آپدیت بشود و از 10% تا 100% را در همان خط چاپ کند و دیگر به خط بعدی نرود چه باید کرد ؟ یه مثال دیگه ... مدیربسته‌های dnf , apt , pacman که نوارپیشرفتی در خروجی کنسول خود نشان میدن.
  11. قاسم رمضانی منش

    با تشکر از توضیحات شما @فرهاد شیری . بنده اون لینکی که پیشنهاد داده بودید و به‌علاوه موارد دیگری هم در این زمینه خوانده بودم. و دقیقاً سعی کردم مثالی مرتبط به این موضوع بزنم. پس یه نگاه دیگه به فایل هدری که مثال زده بودم بکنید : class Base{ public : Base(){std::cout << "BASE#c";} ~Base(){std::cout << "BASE#d";} }; void AnotherTest (void){} void AndAnotherTest(void){} در فایل main.cpp من تنها یک بار تابع AndAnotherTest() را فراخوانی کرده بودم. که مسلماً طبق چیزی که گفتید : و بنده به این صورت برداشت کردم : که ابتدا تمام کد های فایل هدر من کامپایل شده و سپس در زمان لینک ، لینکر می‌بایست تنها لینکی به تابع AndAnotherTest() داشته باشد. و فقط هم این تابع در خروجی کد من باشد. من برای تست این موضوع از تعریف یک کلاس و دو تابع استفاده کردم. از آن‌جایی که میدونستم کلاس تنها یه نقشه از ساختمان است. پس تا زمانی که از این نقشه نمونه‌سازی نشوند ، نباید هیچ حافظه‌ای یا کامپایلی برای کد های این کلاس درنظر گرفته بشه. که تا این قسمت با توجه به خروجی اسمبلی من درست بود و حرفی از کلاس Base زده نشده بود. اما درمورد دوتا تابع بعدی که دقیقا هر دو کامپایل و درخروجی کد من بودن. در مقایسه هایی که کردم (که تماماً در طوماری که بالا ارسال کردم ، ذکر شده) متوجه شدم تنها تفاوت در فایلی که من تابع را فراخوانی و در فایلی که فراخوانی نکرده بودم تنها یک خط در خروجی اسمبلی بود ؛ اون‌هم دستور فراخوانی تابع AndAnotherTest() : [ghasem@clibcore output]$ cat --number JustHeader | egrep "(AnotherTest|AndAnotherTest)" > OnlyHeaderGREP [ghasem@clibcore output]$ cat --number UseOneFunction | egrep "(AnotherTest|AndAnotherTest)" > UseOneFunctionGREP [ghasem@clibcore output]$ diff JustHeader UseOneFunction 55d54 < call _Z14AndAnotherTestv در مورد هدرفایل iostream هم. متغیرها و توابعی که به صورت static یا non-member function تعریف شده‌اند ، خروجی اسمبلی‌شان در فایل نهایی من هست. به غیر از tamplate-function و template-class و class ها که آن‌ها دقیقا برای کامپایل شدن نیاز به استفاده شدن را دارند. الان دلیل این اتفاق : وجود کد اسمبلی تابع استفاده نشده در فایل هدر ، در خروجی نهایی فایل ترجمه شده به اسمبلی من چیست ؟ و آیا راهی برای جلوگیری از این موضوع هست ؟
  12. قاسم رمضانی منش

    (عذرخواهی میکنم مطالبی ارسالی این پست به دلیلی خروجی اسمبلی کدها طولانی و خارج از حوصله است. لذا متن‌های بین کدها با سبک دُرُشت و اندازه ۱۸ نوشته شده است) خب مگه اون هدر فایلی که اضافه میکنیم کامپایل نمیشه ؟ الان یک نمونه تستی که من نوشتم : header.hpp class Base{ public : Base(){std::cout << "BASE#c";} ~Base(){std::cout << "BASE#d";} }; void AnotherTest (void){} void AndAnotherTest(void){} main.cpp #include <iostream> #include "header.hpp" int main(){ return 0; } خروجی اسمبلی زیر را تولید کرده : .file "main.cpp" .text .section .rodata .type _ZStL19piecewise_construct, @object .size _ZStL19piecewise_construct, 1 _ZStL19piecewise_construct: .zero 1 .local _ZStL8__ioinit .comm _ZStL8__ioinit,1,1 .text .globl _Z11AnotherTestv .type _Z11AnotherTestv, @function _Z11AnotherTestv: .LFB1524: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 nop popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1524: .size _Z11AnotherTestv, .-_Z11AnotherTestv .globl _Z14AndAnotherTestv .type _Z14AndAnotherTestv, @function _Z14AndAnotherTestv: .LFB1525: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 nop popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1525: .size _Z14AndAnotherTestv, .-_Z14AndAnotherTestv .globl main .type main, @function main: .LFB1526: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $0, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1526: .size main, .-main .type _Z41__static_initialization_and_destruction_0ii, @function _Z41__static_initialization_and_destruction_0ii: .LFB2010: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $16, %rsp movl %edi, -4(%rbp) movl %esi, -8(%rbp) cmpl $1, -4(%rbp) jne .L7 cmpl $65535, -8(%rbp) jne .L7 movl $_ZStL8__ioinit, %edi call _ZNSt8ios_base4InitC1Ev movl $__dso_handle, %edx movl $_ZStL8__ioinit, %esi movl $_ZNSt8ios_base4InitD1Ev, %edi call __cxa_atexit .L7: nop leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE2010: .size _Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii .type _GLOBAL__sub_I__Z11AnotherTestv, @function _GLOBAL__sub_I__Z11AnotherTestv: .LFB2011: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $65535, %esi movl $1, %edi call _Z41__static_initialization_and_destruction_0ii popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE2011: .size _GLOBAL__sub_I__Z11AnotherTestv, .-_GLOBAL__sub_I__Z11AnotherTestv .section .init_array,"aw" .align 8 .quad _GLOBAL__sub_I__Z11AnotherTestv .hidden __dso_handle .ident "GCC: (GNU) 8.2.1 20181105 (Red Hat 8.2.1-5)" .section .note.GNU-stack,"",@progbits و کد زیر : #include <iostream> #include "header.hpp" int main(){ AndAnotherTest(); return 0; } خروجی اسمبلی زیر را تولید کرده : .file "main.cpp" .text .section .rodata .type _ZStL19piecewise_construct, @object .size _ZStL19piecewise_construct, 1 _ZStL19piecewise_construct: .zero 1 .local _ZStL8__ioinit .comm _ZStL8__ioinit,1,1 .text .globl _Z11AnotherTestv .type _Z11AnotherTestv, @function _Z11AnotherTestv: .LFB1524: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 nop popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1524: .size _Z11AnotherTestv, .-_Z11AnotherTestv .globl _Z14AndAnotherTestv .type _Z14AndAnotherTestv, @function _Z14AndAnotherTestv: .LFB1525: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 nop popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1525: .size _Z14AndAnotherTestv, .-_Z14AndAnotherTestv .globl main .type main, @function main: .LFB1526: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 call _Z14AndAnotherTestv movl $0, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1526: .size main, .-main .type _Z41__static_initialization_and_destruction_0ii, @function _Z41__static_initialization_and_destruction_0ii: .LFB2010: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $16, %rsp movl %edi, -4(%rbp) movl %esi, -8(%rbp) cmpl $1, -4(%rbp) jne .L7 cmpl $65535, -8(%rbp) jne .L7 movl $_ZStL8__ioinit, %edi call _ZNSt8ios_base4InitC1Ev movl $__dso_handle, %edx movl $_ZStL8__ioinit, %esi movl $_ZNSt8ios_base4InitD1Ev, %edi call __cxa_atexit .L7: nop leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE2010: .size _Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii .type _GLOBAL__sub_I__Z11AnotherTestv, @function _GLOBAL__sub_I__Z11AnotherTestv: .LFB2011: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $65535, %esi movl $1, %edi call _Z41__static_initialization_and_destruction_0ii popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE2011: .size _GLOBAL__sub_I__Z11AnotherTestv, .-_GLOBAL__sub_I__Z11AnotherTestv .section .init_array,"aw" .align 8 .quad _GLOBAL__sub_I__Z11AnotherTestv .hidden __dso_handle .ident "GCC: (GNU) 8.2.1 20181105 (Red Hat 8.2.1-5)" .section .note.GNU-stack,"",@progbits و در کد اسمبلئ که هیچ یک از توابع فایلheader.hpp استفاده نشده است. خروجی اسمبلی توابع فایل header.hpp موجود هست : [ghasem@clibcore tmp]$ cat --number OnlyHeader | egrep "(AnotherTest|AndAnotherTest)" 11 .globl _Z11AnotherTestv 12 .type _Z11AnotherTestv, @function 13 _Z11AnotherTestv: 27 .size _Z11AnotherTestv, .-_Z11AnotherTestv 28 .globl _Z14AndAnotherTestv 29 .type _Z14AndAnotherTestv, @function 30 _Z14AndAnotherTestv: 44 .size _Z14AndAnotherTestv, .-_Z14AndAnotherTestv 92 .type _GLOBAL__sub_I__Z11AnotherTestv, @function 93 _GLOBAL__sub_I__Z11AnotherTestv: 109 .size _GLOBAL__sub_I__Z11AnotherTestv, .-_GLOBAL__sub_I__Z11AnotherTestv 112 .quad _GLOBAL__sub_I__Z11AnotherTestv و در کدی که فقط تابع AndAnotherTest() استفاده شده است : [ghasem@clibcore tmp]$ cat --number UseOneFunction | egrep "(AnotherTest|AndAnotherTest)" 11 .globl _Z11AnotherTestv 12 .type _Z11AnotherTestv, @function 13 _Z11AnotherTestv: 27 .size _Z11AnotherTestv, .-_Z11AnotherTestv 28 .globl _Z14AndAnotherTestv 29 .type _Z14AndAnotherTestv, @function 30 _Z14AndAnotherTestv: 44 .size _Z14AndAnotherTestv, .-_Z14AndAnotherTestv 55 call _Z14AndAnotherTestv 93 .type _GLOBAL__sub_I__Z11AnotherTestv, @function 94 _GLOBAL__sub_I__Z11AnotherTestv: 110 .size _GLOBAL__sub_I__Z11AnotherTestv, .-_GLOBAL__sub_I__Z11AnotherTestv 113 .quad _GLOBAL__sub_I__Z11AnotherTestv و تنها تفاوت این دو در فراخوانی تابع AndAnotherTest() هست : [ghasem@clibcore output]$ cat --number JustHeader | egrep "(AnotherTest|AndAnotherTest)" > OnlyHeaderGREP [ghasem@clibcore output]$ cat --number UseOneFunction | egrep "(AnotherTest|AndAnotherTest)" > UseOneFunctionGREP [ghasem@clibcore output]$ diff JustHeader UseOneFunction 55d54 < call _Z14AndAnotherTestv در حالی که من از پاسخ شما @سروش ربیعی فهمیدم که گفتید هدرفایل‌ها تاثیری در حجم برنامه‌ٔ‌نهایی نداره. اما مثال بالا که زدم با وجود اینکه هیچ فراخوانی از توابع نشده بود بازم هم کد های هدرفایل کامپایل شد. و اما بخشی که منو گیج کرده ! ما در این فایل هم هدرفایل iostream و هم header.hpp را وارد برنامه کرده ایم. توابعی که در header.hpp بود تماما کامپایل شده و در خروجی اسمبلی هست. اما خبری از توابع و دستورات iostream نیست. این خروجی اسمبلی بدون هدرفایل iostream هست : .file "main.cpp" .text .globl _Z11AnotherTestv .type _Z11AnotherTestv, @function _Z11AnotherTestv: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 nop popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size _Z11AnotherTestv, .-_Z11AnotherTestv .globl _Z14AndAnotherTestv .type _Z14AndAnotherTestv, @function _Z14AndAnotherTestv: .LFB1: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 nop popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1: .size _Z14AndAnotherTestv, .-_Z14AndAnotherTestv .globl main .type main, @function main: .LFB2: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $0, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE2: .size main, .-main .ident "GCC: (GNU) 8.2.1 20181105 (Red Hat 8.2.1-5)" .section .note.GNU-stack,"",@progbits و تفاوت آن با خروجی اسمبلی‌ای که هدرفایل iostream وجود داشته است : [ghasem@clibcore output]$ diff WithIostream WithoutIostrea 3,10d2 < .section .rodata < .type _ZStL19piecewise_construct, @object < .size _ZStL19piecewise_construct, 1 < _ZStL19piecewise_construct: < .zero 1 < .local _ZStL8__ioinit < .comm _ZStL8__ioinit,1,1 < .text 14c6 < .LFB1518: --- > .LFB0: 26c18 < .LFE1518: --- > .LFE0: 31c23 < .LFB1519: --- > .LFB1: 43c35 < .LFE1519: --- > .LFE1: 48c40 < .LFB1520: --- > .LFB2: 60c52 < .LFE1520: --- > .LFE2: 62,113d53 < .type _Z41__static_initialization_and_destruction_0ii, @function < _Z41__static_initialization_and_destruction_0ii: < .LFB2001: < .cfi_startproc < pushq %rbp < .cfi_def_cfa_offset 16 < .cfi_offset 6, -16 < movq %rsp, %rbp < .cfi_def_cfa_register 6 < subq $16, %rsp < movl %edi, -4(%rbp) < movl %esi, -8(%rbp) < cmpl $1, -4(%rbp) < jne .L7 < cmpl $65535, -8(%rbp) < jne .L7 < movl $_ZStL8__ioinit, %edi < call _ZNSt8ios_base4InitC1Ev < movl $__dso_handle, %edx < movl $_ZStL8__ioinit, %esi < movl $_ZNSt8ios_base4InitD1Ev, %edi < call __cxa_atexit < .L7: < nop < leave < .cfi_def_cfa 7, 8 < ret < .cfi_endproc < .LFE2001: < .size _Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii < .type _GLOBAL__sub_I__Z11AnotherTestv, @function < _GLOBAL__sub_I__Z11AnotherTestv: < .LFB2002: < .cfi_startproc < pushq %rbp < .cfi_def_cfa_offset 16 < .cfi_offset 6, -16 < movq %rsp, %rbp < .cfi_def_cfa_register 6 < movl $65535, %esi < movl $1, %edi < call _Z41__static_initialization_and_destruction_0ii < popq %rbp < .cfi_def_cfa 7, 8 < ret < .cfi_endproc < .LFE2002: < .size _GLOBAL__sub_I__Z11AnotherTestv, .-_GLOBAL__sub_I__Z11AnotherTestv < .section .init_array,"aw" < .align 8 < .quad _GLOBAL__sub_I__Z11AnotherTestv < .hidden __dso_handle با یه نگاه کردن به فایل iostream : #ifndef _GLIBCXX_IOSTREAM #define _GLIBCXX_IOSTREAM 1 #pragma GCC system_header #include <bits/c++config.h> #include <ostream> #include <istream> namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION extern istream cin; extern ostream cout; extern ostream cerr; extern ostream clog; #ifdef _GLIBCXX_USE_WCHAR_T extern wistream wcin; extern wostream wcout; extern wostream wcerr; extern wostream wclog; #endif static ios_base::Init __ioinit; _GLIBCXX_END_NAMESPACE_VERSION } #endif ظاهرا دلیل اون تفاوت هم مشخص هست. اما تکلیف مابقی هدرفایل هایی که داخل iostream وارد شده اند چیست ؟ مگه توابع و متغیر های آنها نیز کامپایل نمیشود ؟ پس چرا مثل خروجی کد اسمبلی‌ توابع موجود در header.hpp در سورس اسمبلی نهایی نیست ؟ (و باز عذرخواهی میکنم بابت طولانی بودن پست )
  13. با سلام. درحال بررسی کدهای کتابخانه‌های استاندارد سی‌پلاس‌پلاس بودم ، که متوجه موردی شدم ؛ تقریبا بیشتر توابع و کلاس‌هایی که از کتابخانه‌های استاندارد استفاده میکنیم دارای مقدار زیادی وابستگی به توابع و فایل‌های دیگر دارند. برای مثال تابع std::swap که برای جابه‌جایی دو نوع استفاده میشود به این‌صورت میباشد : template<typename _Tp, size_t _Nm> inline typename std::enable_if<__is_swappable<_Tp>::value>::type swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) noexcept(std::__is_nothrow_swappable<_Tp>::value) { for (size_t __n = 0; __n < _Nm; ++__n) swap(__a[__n], __b[__n]); } که برای کامپایل نیاز به این موارد در دو فایل move.h و type_traits دارند : template<typename _Tp, _Tp __v> struct integral_constant { static constexpr _Tp value = __v; typedef _Tp value_type; typedef integral_constant<_Tp, __v> type; constexpr operator value_type() const noexcept { return value; } #if __cplusplus > 201103L #define __cpp_lib_integral_constant_callable 201304 constexpr value_type operator()() const noexcept { return value; } #endif }; template<bool __v> using __bool_constant = integral_constant<bool, __v>; typedef integral_constant<bool, true> true_type; typedef integral_constant<bool, false> false_type; template<bool, typename _Tp = void> struct enable_if { }; namespace __swappable_details { using std::swap; struct __do_is_swappable_impl { template<typename _Tp, typename = decltype(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))> static true_type __test(int); template<typename> static false_type __test(...); }; struct __do_is_nothrow_swappable_impl { template<typename _Tp> static __bool_constant< noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())) > __test(int); template<typename> static false_type __test(...); }; } template<typename _Tp> struct __is_swappable_impl : public __swappable_details::__do_is_swappable_impl { typedef decltype(__test<_Tp>(0)) type; }; template<typename _Tp> struct __is_swappable : public __is_swappable_impl<_Tp>::type { }; template<typename _Tp> struct __is_nothrow_swappable_impl : public __swappable_details::__do_is_nothrow_swappable_impl { typedef decltype(__test<_Tp>(0)) type; }; template<typename _Tp> struct __is_nothrow_swappable : public __is_nothrow_swappable_impl<_Tp>::type { }; خب ! سوال اول بنده اینجاس که در چنین مواردی ، بهتر نیست که تابعstd::swap را با توجه به نیازی که داریم خودمان پیاده‌سازی کنیم ؟ و اینکه آیا این حجم از کد و استفاده از template ها هزینه پِرفُورْمَنْس زیادی ندارد ؟ و سوال دوم : تمام این کدها در دو فایل move.h و type_traits قرار دارد (که مسلماً این فایل ها هم وابستگی‌های دیگری به دیگر فایل‌ها دارند). آیا ما نمی‌توانیم مثلا فقط تابع std::swap را در برنامه‌ی خود فراخوانی کنیم که این حجم از کد احتیاج به کامپایل نداشته باشد ؟ برای نمونه در زبان برنامه‌نویسی پایتون ، با استفاده از دستور import ما یک ماژول را وارد برنامه میکنیم : import time در این روش تمام ماژول time به فایل‌ما اضافه خواهند شد. درصورتی که ما فقط از ماژول time نیاز به تابع sleep داشته باشیم کافی است که از قابلت from ... import ... استفاده کنیم : from time import sleep آیا این حرکت در C++ نیز امکان‌پذیر هست ؟
  14. قاسم رمضانی منش

    نه هیچ برنامه‌ای به‌طور خودکار در چند ترد اجرا نمیشه. مرسی بابت پاسخ. بله الان که با خوندن فایل /proc/PID/status متوجه شدم که کلا این برنامه از یک thread بیشتر استفاده نمیکنه :).
  15. قاسم رمضانی منش

    دقیقا متوجه نشدم منظورتان را از محیط توسعه . مشخصات سیستمی که این برنامه را اجرا کرده : OS: Fedora release 29 (Twenty Nine) x86_64 Kernel: 4.19.6-300.fc29.x86_64 CPU: Intel i7 M 620 (4) @ 2.667GHz GPU: NVIDIA NVS 3100M Memory: 3801MiB و کامپایلر g++ (GCC) 8.2.1 20181105 (Red Hat 8.2.1-5) بدون دستکاری فلگ‌ها استفاده با چه فلگ هایی این عمل صورت میگیره ؟
×