پرچمداران
-
در همه بخش ها
- همه بخش ها
- فایل
- دیدگاه فایل
- نقد و بررسی فایل
- مقالات
- مقاله دیدگاه
- مقاله نقد و بررسی
- صفحات استاتیک
- صفحه دیدگاه
- صفحه نقد و بررسی
- کتابخانهها
- کتابخانه دیدگاه
- کتابخانه نقد و بررسی
- رویداد
- دیدگاه های رویداد
- بازبینی رویدادها
- تصاویر
- دیدگاه های تصویر
- نقد های تصویر
- آلبوم ها
- نظر های آلبوم
- نقد های آلبوم
- پست ها
- نوشتههای وبلاگ
- دیدگاه های وبلاگ
- بروزرسانی وضعیت
- پاسخ های دیدگاه ها
-
تاریخ سفارشی
-
همه زمان ها
4 خرداد 1397 - 17 اردیبهشت 1403
-
سال
16 اردیبهشت 1402 - 17 اردیبهشت 1403
-
ماه
18 فروردین 1403 - 17 اردیبهشت 1403
-
هفته
10 اردیبهشت 1403 - 17 اردیبهشت 1403
-
امروز
17 اردیبهشت 1403
-
تاریخ سفارشی
سه شنبه, 5 اردیبهشت 1402
-
همه زمان ها
مطالب محبوب
در حال نمایش مطالب دارای بیشترین امتیاز از زمان سه شنبه, 5 اردیبهشت 1402 در همه بخش ها
-
1 امتیازاگر شما توسعه دهندهٔ ++C هستید، توصیه میکنم این سری از مقالات را دنبال کنید زیرا در این تاپیک قصد دارم به چکیدهای از آخرین تغییرات مرتبط با سیپلاسپلاس پیشرفته اشاره کنم. بنابراین در بخش اول، مهمترین موارد منسوخ شده، اشکلات رفع شده و ویژگیهای جدید در استانداردهای اخیر را پوشش خواهیم داد که به صورت جزئی خواهد بود و سپس نسبت به هر کدام در مقالات جداگانه به کاربردهای پیشرفتهتر و جزئیات بیشتری اشاره خواهیم کرد. قبل از شروع، اگر میخواهید به لیستی از تغییرات و ویژگیهای کامل در استانداردها دسترسی داشته باشید به مقالهٔ زیر مراجعه کنید. در مقالهٔ فوق به لیست ویژگیهای جدید در استاندارد ۱۱، ۱۴، ۱۷ و ۲۰ اشاره شده است. در نظر داشته باشید که بزرگترین بهروز رسانی سی++ در ده سالِ اخیر مربوط به استاندارد ۲۰ است. این نسخه از زبان تقریباً 2.5 برابر بزرگتر از سی++ ۱۰ سال پیش است! این در حالی است که استاندارد ۱۷ تقریباً ۸۰٪ بزرگتر از استاندارد ۰۳ است. به عنوان مثال، طبق مستندات رسمی پیشنویسهها تغییرات استاندارد از ۸۷۹ صفحه به ۱۸۳۴ صفحه در این استاندارد رسیده است! چیزی حدود ۱۰۰۰ صفحه بیشتر از نسخههای قبلی ? تمامی این بهبودها خبر از بهتر شدن و در عین حال پیچیده شدن زبان اما همراه با سادهتر و سریعتر شدن آن میدهد. اما مشکلی که میتواند رخ دهد در این است که یادگیری آن و بهروزرسانی کدها نیز میتواند دردسر ساز باشد. بنابراین، برای پوشش دادن جزئیات و بهروزرسانیهای بیشتر در این مقاله سعی خواهم کرد که مهمترین موارد را معرفی کنم. جزئیات ++C نسخه ۱۷ (بهبودها و تغییرات) بیایید به آرامی شروع کنیم، امروز ما به عناصر حذف شده و یا به موارد بهبود یافتهٔ کتابخانه استاندارد بپردازیم. معرفی به صورت سلسله مراتبی عناصر حذف شده و توسعه یافته (در این بحث) شفاف سازی در زبان قالبها ویژگیها تغییرات اول کتابخانه تغییرات دوم کتابخانه مستندات و لینکها قبل از هر چیز، اگر شما خودتان میخواهید استاندارد جدید را کاوش کنید آخرین پیش نویسه را در این بخش مطالعه کنید. در صورتی که میخواهید بدانید کدام کامپایلر از ویژگیهای جدید پشتیبانی میکند، در این بخش آن را پیگیری کنید. علاوه بر این، لیستی از توصیفهای مختصر از تمامی ویژگیهای زبان سیپلاسپلاس ۱۷ تهیه شده است که در این بخش میتوانید آن را ببینید که در قالب PDF از طرف مرجع رسمی میباشد. مواردی که ترجیح داده شده است که حذف شوند حذف تریگراف تریگرافها کاراکترهای ویژه ترتیبی هستند که در موقع عدم پشتیبانی سیستم از نوع ۷ بیتی اَسکی (ASCII) همانند ایزو 646 استفاه شوند. برای مثال =?? کاراکتر ویژهای مانند # تولید شده را در قالب -?? تولید میکند. تمامی مجموعه کاراکترهای اصلی سیپلاسپلاس در قالب 7 بیتی اسکی قرار دارند. موضوع فوق به ندرت مورد استفاده قرار میگیرد، بنابراین حذف آن ممکن است به ترجمه ساده کد کمک کند. اگر شما میخواهید اطلاعات بیشتری در رابطه با کارآیی تیرگرافها در سی++ کسب کنید به این لینک مراجعه کنید. ---------------------------------------------------------------------------- | trigraph | replacement | trigraph | replacement | trigraph | replacement | ---------------------------------------------------------------------------- | ??= | # | ??( | [ | ??< | { | | ??/ | \ | ??) | ] | ??> | } | | ??’ | ˆ | ??! | | | ??- | ˜ | ---------------------------------------------------------------------------- شما جزئیات بیشتر را میتوانید در سند N4086 بیابید. اگر شما واقعاً به هر نحوی به گرافها در ویژوال استودیو نیاز دارید، نگاهی به مشخصه /Zc:trigraphs در بخش پیکربندی داشته باشید. همچنین، کامپایلرهای دیگر ممکن است مواردی را پشتیبانی نکنند. وضعیت انجام شده کنونی در کامپایلر های GCC:5.1 و Clang:3.5 میباشد. حذف کلمه کلیدی register کلمه کلیدی register در استاندارد 2011 سیپلاسپلاس منسوخ شده است و دیگر استفاده از آن معنایی ندارد. این کلمه کلیدی در حال حاضر حذف شده است. این کلمه کلیدی محفوظ است و ممکن است در نسخه های بعدی باز نویسی شود (مثلا autokeyword به عنوان یک چیز قدرتمند مجددا مورد استفاده قرار گرفته است). جزئیات بیشتر در رابطه با این مورد در P0001R1 قابل مشاهده است. البته فعلا در MSVC انجام نشده است اما در کامپایلرهای GCC 7.0 و Clang 3.8 انجام شده است. حذف Operator++ bool این اپراتور برای زمان بسیار زیادی است که منسوخ شده است! در سی پلاس پلاس ۹۸ تصمیم بر آن گرفته بودند که از آن استفاده کنند اما در نسخه ۱۷ سیپلاسپلاس کمیته موافقت خود را جهت حذف آن از زبان اعلام کرده است. جزئیات بیشتر در رابطه با این مورد در P0002R1 قابل مشاهده است. البته فعلا در MSVC انجام نشده است اما در کامپایلرهای GCC 7.0 و Clang 3.8 انجام شده است. حذف مشخصات استثنایی از استاندارد ۱۷ در سی پلاس پلاس ۱۷، مشخصات استثنایی بخشی از نوع سیستمی خواهند بود (به P0012R1 نگاه کنید). با این حال، استاندارد شامل مشخصات استثنایی قدیمی و منسوخ شده اند که به نظر غیرعلمی و غیرقابل استفاده است. void fooThrowsInt(int a) throw(int) { printf_s("can throw ints\n"); if (a == 0) throw 1; } کد بالا در سیپلاسپلاس ۱۱ رد (منسوخ شده است). تنها اعلامیه استثنایی علمی throw() است، به این معنی است که این کد چیزی را در قالب throw انجام نخواهد داد. اما از سیپلاسپلاس ۱۱ به اینور، برنامه نویسان توصیه کرده اند که کسی از آن استفاده نکند. برای مثال در کامپایلر Clang 4.0 شما باید خطای زیر را دریافت کنید: error: ISO C++1z does not allow dynamic exception specifications [-Wdynamic-exception-spec] note: use 'noexcept(false)' instead جزئیات بیشتر در رابطه با این مورد در P0003R5 قابل مشاهده است. البته فعلا در MSVC انجام نشده است اما در کامپایلرهای GCC 7.0 و Clang 3.8 انجام شده است. حذف auto_ptr این یکی از به روز رسانیهای خوبی است که در سیپلاسپلاس ۱۱، ما اشاره گرهای هوشمند را دریافت کردیم : unique_ptr,shared_ptr و weak_ptr. با تشکر از این حرکتی که کمیته انجام داده بود، معنای واقعی این به روز رسانی در این بود که زبان میتواند پشتیبانی مناسبی از انتقال منابع منحصربفرد را داشته باشد. در این میان auto_ptr یک چیز قدیمی و نادرست در زبان بود به نا به دلایلی auto_ptr در این جا منسوخ شده است و باید به صورت خودکار به unique_ptr تبدیل شود. توجه داشته باشیم که auto_ptr مدت کوتاهی است که از سیپلاسپلاس ۱۱ به اینور منسوخ شده است و بسیاری از کامپایلر ها منسوخ شدن آن را گزارش میدهند که به صورت زیر خواهد بود: warning: 'template<class> class std::auto_ptr' is deprecated در حال حاضر آن به وضعیت نامناسب تبدیل شده است، و اساساً کد شما کامپایل نخواهد شد. در اینجا خطا از طرف MSVC 2017 زمانی که از گزینه /std::c++latest استفاده کنید اعلام خواهد شد. error C2039: 'auto_ptr': is not a member of 'std' اگر شما نیاز به کمک از تبدیل از auto_ptr به unique_ptr دارید، میتوانید Clang Tidy را بررسی کنید، زیرا آن عمل تبدیل خودکار را انجام خواهد داد. اطلاعات بیشتر در سند N4190 موجود است. همچنین موارد مرتبط دیگری با سند N4190 وجود دارند که در کتابخانه خذف شده اند مانند: unary_function/binary_function ptr_fun() mem_fun()/mem_fun_ref() bind1st()/bind2nd() random_shuffle قوانین جدید خودکار برای Direct-List-Initialization از سی پلاس پلاس ۱۱ به اینور که ما یک مشکل بزرگی در این رابطه داشتیم: auto x { 1 }; از initializer_list اینطور نتیجهگیری شده است. با استاندارد جدید، ما میتوانیم این مشکل را حل کنیم. بنابراین آن میتواند به عنوان نوع int که اکثر مردم تصور میکنند شناسایی شود. برای اینکه این اتفاق بیافتد، ما نیاز داریم که دو روش تخصیص مقدار اولیه را درک کنیم: کپی و مستقیم. auto x = foo(); // copy-initialization auto x{foo}; // direct-initialization, initializes an // initializer_list (until C++17) int x = foo(); // copy-initialization int x{foo}; // direct-initialization برای مقدار دهی اولیه، سیپلاسپلاس ۱۷ قوانین جدیدی را معرفی میکند: For a braced-init-list with only a single element, auto deduction will deduce from that entry; For a braced-init-list with more than one element, auto deduction will be ill-formed. برای مثال: auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int> auto x2 = { 1, 2.0 }; // error: cannot deduce element type auto x3{ 1, 2 }; // error: not a single element auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int> auto x5{ 3 }; // decltype(x5) is int جزئیات بیشتر را در سند N3922 میتوانید مشاهده کنید. همچنین جزئیات در رابطه با فهرست خودکار موجود هستند که توسط جناب آقای Ville Voutilainen اشاره شده است. این اضافات در سیپلاسپلاس از زمان MSVC 14.0، GCC 5.0 و Clang 3.8 کار میکنند. گزینه static_assert بدون هیچ نوع پیغامی این واضح است که، این به شما این امکان را می دهد که فقط بدون داشتن گذراندن پیام، نسخه دارای پیغام در دسترس خواهد بود. این سازگاری با سایر موارد مانند BOOST_STATIC_ASSERT وجود دارد. static_assert(std::is_arithmetic_v<T>, "T must be arithmetic"); static_assert(std::is_arithmetic_v<T>); // no message needed since C++17 جزئیات بیشتر در سند N3928 در دسترس است. پشتیبانی شده در MSVC 2017 ٬ GCC 6.0 و Clang 2.5. انواع مختلف شروع و پایان در محدوده حلقه از سیپلاسپلاس ۱۱ به بعد، محدوده مبتنی بر حلقه ها به صورت داخلی تعریف شده است: { auto && __range = for-range-initializer; for ( auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } } همانطور که میبینید، __begin و __end دارای نوع مشابه هستند. این ممکن است باعث مشکلاتی شود. برای مثال زمانی که شما چیزی شبیه یک نگهبان (محافظ) که از نوع داده دیگری است را داشته باشید مشکل ساز خواهد بود. در سیپلاسپلاس ۱۷ آن به صورت زیر تغییر کرده است: { auto && __range = for-range-initializer; auto __begin = begin-expr; auto __end = end-expr; for ( ; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } } انواع __begin و __end ممکن است متفاوت باشد چرا که فقط اپراتور مقایسه مورد نیاز است. این تغییر کلی باعث میشود که این ویژگی تجربه بیشتری را در این زمینه برای کاربران ارائه دهند. جزئیات بیشتر در P0184R0، پشتیبانی شده در MSVC 2017 ،GCC 6.0 و Clang 3.6.
-
1 امتیاز
-
1 امتیازاحساس افسردگی و اسکلی کردم آخه با وجود اینکه تا بحال روی دو تا پروژه کار کردم و شاغلم فهمیدم زیادی سریع فکر کردم دیگه همه چیز دانم و باید کار را شروع کنم حداقل نصف چیزایی که گفتی را بلد نیستم (البته خوشحالم که هنوز راه زیادی برای یادگیری در پیش دارم راه خیلی زیاد ...)
-
1 امتیازجزئیات، بهروز رسانیها و ویژگیهای C++20 معرفی و نمونه کدهای کلاس std::span کلاس std::span یک کلاس در C++20 است که برای نشان دادن (نمایش ظاهری) یک محدوده دنبالهای از اشیاء پیوسته بکار میرود. الگوی کلاس span یک شیء را توصیف میکند که میتواند به یک دنباله متوالی از اشیاء با اولین عنصر دنباله در موقعیت صفر ارجاع دهد. یک span میتواند دارای دامنهی استاتیک باشد، در این صورت تعداد عناصر در دنباله در زمان کامپایل مشخص است و در نوع خودشان رمزگذاری شدهاند و یا دامنهی داینامیک دارد. اگر یک span دارای دامنهٔ داینامیک باشد، به طور معمول، پیادهسازی آن شامل دو عضو است: یک اشارهگر به T و یک اندازه است. یک span با دامنهٔ استاتیک ممکن است فقط یک عضو داشته باشد: یک اشارهگر به T. template< class T, std::size_t Extent = std::dynamic_extent > class span; برای استفاده از کلاس std::span، باید ابتدا کتابخانه <span> را به کدتان اضافه کنید. سپس برای ایجاد یک شیء از این کلاس، میتوانید از یک اشارهگر به شروع دنباله و طول آن استفاده کنید. برای مثال: #include <span> #include <iostream> int main() { int arr[] = {1, 2, 3, 4, 5}; std::span<int> mySpan(arr, 5); for (int i : mySpan) { std::cout << i << " "; } return 0; } در این مثال، یک آرایه از نوع int با ۵ عضو تعریف شده و سپس یک شیء از کلاس std::span با استفاده از این آرایه و طول آن ایجاد میشود. سپس با استفاده از حلقه for، اعضای دنباله در خروجی چاپ میشوند. استفاده از std::span میتواند در کدهایی که بر روی دادههای چند بعدی یا برای دادههایی که آنها نمیتوانند با طول ثابت در داخل یک آرایه شبیهسازی شوند، مفید باشد. همچنین، با استفاده از std::span میتوان با مراجعه به همه اعضای یک آرایه به صورت پویا از زمان اجرا، از یک پیادهسازی معمولی با تراکم حافظه کمتر استفاده کرد. همچنین استفاده از std::span برای پشتیبانی از روشهای پیشرفتهتر و بازبینی کدها مفید است. اینجا یک نمونه از استفاده از std::span در یک کد C++20 آورده شده است: #include <iostream> #include <span> int main() { int arr[] = {1, 2, 3, 4, 5}; std::span<int, 5> s(arr); // s refers to the whole array for (auto& elem : s) { // range-based for loop std::cout << elem << ' '; } std::cout << '\n'; std::span<int, 3> s2(arr + 1, 3); // s2 refers to {2, 3, 4} for (auto& elem : s2) { std::cout << elem << ' '; } std::cout << '\n'; } در این کد، یک آرایه از 5 عدد تعریف شده است. سپس با استفاده از std::span، دو نمونه برای این آرایه تعریف شده است. پس از آن ، با استفاده از حلقه for ، مقادیر در هر دو نمونه std::span به ترتیب چاپ شده و تفاوت بین آنها نیز نشان داده شده است. برخی از مزایای این کلاس به صورت زیر است: کد مطمئنتر: به دلیل استفاده از نمای مناسبی از ارثبری، این کلاس امکان بازنویسی کد و تجدید نظر در طراحی را فراهم میکند. کاربردهای متعدد: توانایی نشان دادن دادههای پیوسته با هر نوع، دنبالههای داخلی و خارجی، بردارها، ماتریسها و موارد دیگر، std::span را به یک وسیله کارآمد در برنامهنویسی ترکیبشدها و همزمانسازی دادهها تبدیل کرده است. عملکرد بهتر: به دلیل این که std::span یک کلاس ساده به همراه تعریف مجددی از iterator (https://en.cppreference.com/w/cpp/iterator) هاست، عملیاتی مانند خواندن، نوشتن و مرتب سازی دادهها، بسیار سریعتر از زیربرنامههای برنامه سازی بهینه شده است. پشتیبانی از تشخیص خطا: با استفاده از std::span، میتوان یک شیء معتبری ایجاد کرد که در آن تغییرات اندیس باید در محدوده معتبر واقع شود که باعث بهبود تشخیص خطا در کد میشود. اینجا یک نمونه کد ورودی با std::span برای محاسبه میانگین اعداد یک محدوده از داده هاست که توضیحات کد نیز در کد ذکر شده است: #include <iostream> #include <span> #include <algorithm> double average(std::span<int> ns) { if (ns.empty()) throw std::invalid_argument("empty span"); if (ns.size() > static_cast<size_t>(std::numeric_limits<int>::max())) throw std::invalid_argument("span size exceeds int max"); if (std::any_of(ns.begin(), ns.end(), [](const int& n) { return n < 0; })) throw std::invalid_argument("span contains negative values"); return static_cast<double>(std::accumulate(ns.begin(), ns.end(), 0)) / ns.size(); } int main() { int arr[] = { 1, 2, 3, 4, 5 }; std::span<int> span_arr(arr, 5); try { std::cout << average(span_arr) << '\n'; } catch(const std::exception& ex) { std::cerr << "Error: " << ex.what() << '\n'; } return 0; } در کد زیر، یک std::span از یک آرایه از اعداد پشت سر هم ایجاد شده است و سپس به عنوان ورودی به تابع calculate_mean() منتقل شده است. تابع calculate_mean() به صورت یک حلقه که به ازای عنصری که به عنوان ورودی دریافت می کند، محدوده داده ها را پیمایش می کند و میانگین اعداد را محاسبه می کند. با استفاده این تابع و تعریف یک آرایه از اعداد، برنامه قادر است میانگین اعداد را محاسبه کند. #include <iostream> #include <span> double calculate_mean(std::span<double> nums) { double sum = 0.0; for (auto num : nums) { sum += num; } return sum / static_cast<double>(nums.size()); } int main() { double nums[] = {2.0, 3.0, 5.0, 7.0, 11.0, 13.0}; std::span<double> nums_span(nums, std::size(nums)); double mean = calculate_mean(nums_span); std::cout << "mean = " << mean << std::endl; return 0; } کاربرد std::span در ورودی توابع یکی از استفاده های مهم std::span ، به عنوان ورودی تابع است. با استفاده از std::span به عنوان ورودی، می توان به سادگی یک محدوده از داده ها را به یک تابع انتقال داد و از انتقال داده های اضافی و همچنین رعایت روشن بودن کد استفاده کرد. با استفاده از std::span به عنوان ورودی تابع، عملیات از هر نوع می تواند مستقل از نوع داده های کانتینر باشد و به همین دلیل کد تمیز تر و بیشتر چند منظوره خواهد بود. #include <iostream> #include <span> double calculateAverage(std::span<double> nums) { double sum = 0; for (auto num : nums) { sum += num; } return (nums.size() > 0) ? sum / nums.size() : 0; } int main() { double data[] = {2.5, 3.8, 4.2, 1.7, 6.5}; double average = calculateAverage(data); std::cout << "Average: " << average << std::endl; return 0; } در این کد، تابع calculateAverage یک std::span از نوع double به عنوان ورودی دریافت می کند و با استفاده از آن، میانگین عناصر را محاسبه می کند. سپس در تابع main یک آرایه از اعداد اولیه تعریف شده است که به عنوان ورودی به تابع calculateAverage ارسال می شود و سپس میانگین محاسبه شده چاپ می شود. استفاده از std::span به خصوص زمانی مناسب است که به دنبال ارسال یک محدوده از داده ها به تابع هستیم، بدون آنکه نیاز به کپی کردن داده ها باشد. در این حالت، استفاده از std::span به جای استفاده از نشانگر به عنوان ورودی تابع، توصیه می شود. با استفاده از std::span، می توان محدوده ای از داده ها را مستقیماً به تابع انتقال داد و از کپی نشانگر آندونه و داده های مربوط به آن جلوگیری کرد و در عین حال، کد را شفاف تر و آسان تر قابل فهم نیز می کند. کاربرد std::span در کلاسها استفاده از std::span در کلاس ها، می تواند در طراحی کلاس هایی که بر روی داده هایی فیکسشده کار می کنند، مفید باشد. این کار به تشخیص و جلوگیری از خطرات مربوط به ارجاع به اشاره یا نشانگر اشاره که به محدوده ای خارج از داده های کلاس مستقر شده اند، کمک می کند. #include <span> class DataProcessor { private: std::span<const int> data; public: explicit DataProcessor(std::span<const int> d) : data(d) {} double calculateMean() const { double sum = 0.0; for (auto num : data) { sum += num; } return sum / static_cast<double>(data.size()); } }; همچنین، میتوان با تعریف تابعهایی که با std::span کار می کنند، از صرفه جویی در حجم کدها خود لذت برد. اینجا یک نمونه کد با استفاده از std::span در طراحی یک کلاس برای مدیریت یک آرایه با سایز ثابت است: #include <array> #include <span> template <typename T, std::size_t N> class FixedArray { public: FixedArray(std::array<T, N>& arr) : data(arr), memory(data) { } std::span<T, N> memory; private: std::array<T, N>& data; }; در این کد، FixedArray یک کلاس است که یک آرایه با سایز ثابت را مدیریت میکند. با استفاده از std::span، ما میتوانیم برای نگهداری دادهها از حافظهای استفاده کنیم که قبل تر allocated شده است (در اینجا دادهها از آرایه data استخراج شده و به صورت پویایی در memory نگهداری میشوند). به این ترتیب، ما از خطرات ارجاع به اشاره به محدودههای خارج از داده ها به دلیل دستکاری در آرایه، محافظت میکنیم.
-
1 امتیازدر این مقاله من قصد دارم به معرفی ده فریمورک برتر جهان در بازهٔ سالهای ۲۰۱۹ و ۲۰۲۰ اشاره کنم که در حوزهٔ صنعت وب کاربرد دارند. معمولاً در سایتها، وبلاگها و گروههای تلگرامی حرف از فریمورکهای شناخته شدهای مانند Asp.net core و یا Laravel به گوش میرسد. اما واقعیت این است که فریمورکهایی که در مورد آنها بحث میشود جایگاه خاصی در بین فریمورکهای قدرتمند و به عنوانی ناشناخته مانند Drogon، h2o، ulib و غیره ندارند! جالب است بدانید فریمورکهایی که در ادامه نامهایشان را میشنوید به قدری سریع و قدرتمند هستند که مو بر تنِ شما سیخ خواهد کرد! برای مثال در این مقایسه جایگاه فریمورکهای داتنت به بالاتر از ۵۰ و لاراول به بیشتر از ۲۰۰ رتبه میرسد! این در حالی است که بر خلاف انتظارِ عام، فریمورکهای تحت سی/سی++ و راست به عنوان سریعترین فریمورکها شناخته میشوند. در واقع مقایسه بر اساس نتایج گرفته شده از مرجع Techempower میباشد که هر ساله یک مقایسه در رابطه با کارآیی و کیفیت فریمورکهای وب میپردازد. سنجشِ فوق بر اساس وظایفی مانند سریالسازی جیسان، دسترسی به پایگاه داده و عملیات سمت سرور، پردازش و غیره میباشد. در این آزمایشها عملکرد فریمورک بر روی سیستمعامل، به صورت فولاِستک و میکرو اندازهگیری شده است که هر کدام را در رتبهٔ خاصی از وضعیت آن سوق میدهد. بهترین فریمورکها از نظر بنچمارک (کارآیی) در سال ۲۰۱۹ در دورِ ۱۸ بین ۲۲۰ فریمورک متعلق به h2o و ulib بوده است. کتابخانهٔ h2o یکی از قویترین مواردی است که میتوان به آن اشاره کرد. در سال ۲۰۲۰ این رتبهبندی به نفعِ فریمورک جدیدتری به نام دراگون (Drogon) و مجدداً ulib جمع بندی شده است که نشان میدهد فریمورک ulib به عنوان یکی از برترین فریمورکهای نوشته شده تحت سی و سی++ و همچنین دراگون تحت استانداردهای ۱۴ و ۱۷ زبان برنامهنویسی سیپلاسپلاس معرفی شده است. بنابرین بهتر است در مورد دراگون بیشتر بدانیم: این فریمورک تحت زبان برنامهنویسی ++C در استاندارد ۱۴ و ۱۷ توسعه یافته و بر روی سکوهای لینوکس، مک و ویندوز قابل اجراست. دراگون تحت ویژگی non-blocking I/O کار میکند و سرعت را همراه با دقت بسیار بالایی به خصوص بر روی پلتفرمهای FreeBSD تضمین میکند. لینک مخزن توسعه و کدهای دراگون. مثال از کد اولیه: #include <drogon/drogon.h> using namespace drogon; int main() { app().setLogPath("./") .setLogLevel(trantor::Logger::kWarn) .addListener("0.0.0.0", 80) .setThreadNum(16) .enableRunAsDaemon() .run(); } با توجه به مقایسههای صورت گرفته در آزمایشهای مختلف زیر رتبهبندی فریمورکها مشخص میشود. آزمایشهای فوق بر روی پردازندهٔ Dell R440 Xeon Gold صورت گرفته است که در این لینک آمده است. JSON serialization Single query Multiple queries Fortunes Data updates Plaintext آزمایشهای مربوطه تنها به ۱۰ مورد اول اشاره کرده است، بنابراین برای مشاهدهٔ لیست بیشتر و جزئیات آنها به مرجع آن مراجعه کنید.
-
1 امتیازاصطلاحاتی که بهتر است در مورد C++ مدرن بدانید! داشتم به این فکر میکردم که برخی از مبتدیان برنامهنویسی به خصوص کسانی که به سراغ زبانهایی مثل سی++ میروند معمولاً مستقیم وارد کد نویسی میشوند و به این گمان که آغاز برنامهنویسی یعنی نوشتن یک کد با خروجی «سلام، دنیا»! دریغ از آن که بعضی از موارد مانند «معرفی کامپایلر و انواع آن» و حتی «ساختار برنامههای نوشته شده تحت سیپلاسپلاس» و یا حتی «مدیریت حافظه» را در نظر بگیرند! من معمولاً در مقالات و آموزشهای خودم به این اشاره میکنم که قبل از هر چیز باید با ساختار برنامههای نوشته شدهٔ یک زبان آشنا شد و سپس به بررسی موارد دیگر مانند نحو زبان و یا دیگر ویژگیهای آن. بنابراین، یکی از خطرناکترین عواملی که موجب خونریزی داخلی یک نرمافزار در برنامههای نوشته شده توسط برنامهنویس درC++ میشود عدم مدیریت حافظهٔ اختصاص یافته است که باید بعد از اختصاص یافتن حافظه در زمان معین آن را آزادسازی کند. در صورتی که این کار صورت نگیرد عمل Memory Leak (نَشتِ حافظه) رخ داده است. بسیاری از علاقهمندان بر این باورند که چون سی++ دارای GC یا همان Garbage Collector (زبالهروب) نیست که البته صحیح است! سی++ دارای GC نیست و این امر محدودیت یا نکته ضعف آن هم نیست! سی++ همه چیز را آزادانه در اختیار برنامهنویس قرار میدهد تا خود در زمان مناسب روش مدیریت حافظه را انتخاب کند. در علوم رایانه بازیافت حافظه یا زبالهروبی نوعی مدیریت حافظهٔ خودکار است که عمل مدیریت حافظههای اختصاص یافته شده را به دست میگیرد و اکثر زبانهای برنامهنویسی مانند #C، جاوا و دیگر موارد مشابه به آن مجهز به این ویژگی هستند که البته وجود چنین ابزارهایی میتواند توهمی را ایجاد کند مبنی بر آن که دیگر نیازی به مدیریت منابع نیست، اما در بعضی موارد مدیریت منابع هنوز یک الزام است چرا که منابع آزاد شده هنوز هم دلیل بر نشتِ حافظه هستند. این نشت حافظه زمانی اتفاق میافتد که اشیاء هنوز قابل دسترس از طرف اشیاءای که زنده هستند اما هرگز مورد استفادهٔ دوباره قرار نمیگیرند اتفاق بیافتد. در بسیاری از زبانهای برنامهنویسی این ویژگی وجود دارد که طبیعتاً مدیریت توسط GC راه حل بسیار خوب و بی نقصی نیست. اما با توجه به عدم وجود GC در سی++ اکثراً با روشهای دستی برای مدیریت حافظه میپردازند که رایجترین روش آن استفاده از عمل new و delete در اختصاص دادن و آزادسازی حافظه است. بسیاری از ما با سی++ در دانشگاه و یا دروس مرتبط با مفاهیم اولیه برنامهنویسی آشنا شده ایم، اما معمولاً مفاهیم مربوطه برای نسلهای قبلی و منسوخ شدهٔ این زبان است. بهتر است در نظر داشته باشید که برنامهنویسی مدرن یعنی پیروی از اصول و قوانین جدیدی که در تکامل یافتن یک زبان به کار گرفته میشود. RAII : Resource Acquisition is initialization بنابراین، باید در نظر گرفت مدیریت حافظه از استاندارد ۱۱ به بعد این زبان به روشهای بسیار مدرنتری هوشمند سازی شده است. یکی از بهترین تکنیکهای موجود در هستهٔ زبان اصطلاح Raiiاست. الگوی RAII مخفف «Resource Acquisition is initialization» که به عنوان یک اصطلاح در برنامهنویسی مطرح میشود به صورت یک تکنیک (کنترل تخصیص منابع و آزادسازی آنها) یکی از ویژگیهای اصلی در سیپلاسپلاس است. با قرار دادن چنین کدی دیگر نیاز به فراخوانی آن کد توسط برنامهنویس در مخرب (ویرانگر) نیست و کامپایلر خود این کار را انجام میدهد. به طور کلی این الگو هر شیء را مجبور میسازد تا در زمان مواجه با رفتارهای ناهنجار خود را پاکسازی کند. به طور کلی هنگامی که شما یک شیء را مقداردهی اولیه میکنید، قبل از انجام آن باید منابع مورد نیاز آن را تأمین کنید (در سازنده). هنگامی که یک شیء از محدوده خارج میشود، هر منبعی را که مورد استفاده قرار داده است باید آزاد کند (در مخرب - ویرانگر). نکات کلیدی هرگز نباید یک شیء به حالت نیمه آماده یا نیمه از بین رفته وجود داشته باشد! وقتی که یک شیء ساخته میشود، آن شیء باید در حالت آماده باش برای استفاده باشد. وقتی یک شیء از محدوده خارج میشود، باید منابع اختصاص یافتهٔ خود را در حافظه آزاد کند (کاربر مجبور به انجام کار دیگری نیست). آیا RAII عنوان بدی برای مفهوم این تکنیک است! از نظر خالق سیپلاسپلاس نام بهتر میتواند به صورت زیر باشد: مدیریت منابع مبتنی بر حوزه (محدوده یا دامنه) : Scope Based Resource Management چیزی که تکنیک RAII را نقض میکند چیست؟ اشارهگرهای خام و تخصیص حافظه فراخوانی با کلمهٔ کلیدی new برای دست آوردن یا اختصاص دادن منبع (حافظه). فراخوانی با کلمهٔ کلیدی delete برای آزادسازی منبع (حافظه). اما این مورد به صورت خودکار بعد از خروج از محدوده توسط اشارهگرها صورت نمیگیرد. void rawPtrFn() { // acquire memory resourceNode* n = newNode; // manually release memory delete n; } بنابراین در صورتی که برنامهنویس استفاده از کلمهٔ کلیدی delete را برای آزادسازی حافظه فراموش کند (نشتِ حافظه) رخ میدهد. این عمل کافی است تا تکنیک RAII را نقض کنیم. void UseRawPointer() { // Using a raw pointer -- not recommended. Song* pSong = new Song(L"Nothing on You", L"Kambiz Asadzadeh"); // Use pSong... // Don't forget to delete! delete pSong; } بنابراین، راه حل RAII برای این امر در چیست؟ کلاسی داشته باشید که : حافظه را هنگام مقداردهی اولیه تخصیص دهد. حافظه را هنگام فراخوانی مخرب (ویرانگر) آزاد کند. دسترسی به اشارهگرهای زیرین را امکانپذیر کند. اشارهگرهای هوشمند (Smart Pointers) یک اشارهگر هوشمند یک شیء به سبکِ RAII است که تضمین میکند یک اشارهگر در هر زمانی که مناسب باشد حافظهٔ اختصاص یافته شده را آزاد میکند. به عنوان یک قاعده، برنامههای نوشته شده در سیپلاسپلاس مدرن (پیشرفته) هرگز نباید از اشارهگرهای خام (Raw) برای مدیریت حافظهٔ پویا (مشترک) استفاده کنند. برنابراین، در برنامههای مدرن سی++ به ندرت باید از کلمهٔ کلیدی delete جهت آزادسازی حافظه استفاده کرد. در واقع انجام این روش موجب جلوگیری از نشت حافظه است. این ویژگی اساساً مدیریت حافظهٔ خودکار را ارائه میدهد. زمانی که یک اشارهگر هوشمند دیگر استفاده نمیشود (زمانی که از محدودهٔ خود خارج میشود) حافظهٔ مورد نظر خود را به طور خودکار آزاد میکند.توجه داشته باشید که اشارهگرهای سنتی با عنوان اشارهگرهای خام (Raw Pointer) شناخته میشوند. اشارهگرهای هوشمند را میتواند یک شکل کلی از GC در نظر گرفت؛ نوعی مدیریت خودکار وقتی که دیگر توسط برنامه مورد استفاده قرار نمیگیرند حافظهٔ اختصاص یافتهٔ آن شیء به طور خودکار حذف میشود. در استاندارد ۱۱ سیپلاسپلاس سه نوع اشارهگر هوشمند معرفی شده است که همهٔ آنها در فایل سرآیند <memory> از کتابخانهٔ استاندارد STL معرفی شدهاند. کلاس std::unique_ptr یک اشارهگر هوشمند که دارای یک منبع تخصیص حافظهٔ پویا است. این شیء دارای یک اشارهگر به حافظهٔ پشته است، بنابراین نمیتوان آن را کپی کرد. تنها میتوان آن را جابجا (move) و مبادله کرد. خارج از این بیشتر مانند یک اشارهگر عادی رفتار میکند. { std::unique_ptr<Person> person(new Person("Kambiz")); if (person != nullptr) person->SetLastName("Asadzadeh"); if (person) DoSomethingWith(*person); } اگر دقت کنید، اپراتورهای -> و * اطمینان میدهد که unique_ptr میتواند اکثر اوقات شبیه به یک اشارهگر خام (Raw Pointer) استفاده شود. کاربردهای معمول از unique_ptr که باعث میشود از آن را به یک ابزار واقعی و ضروری تبدیل کند به صورت زیر است: آنها را میتوان با خیال راحت در داخل یک ظرف (Container) ذخیره کرد. هنگامی که به عنوان متغیرهای عضو کلاس دیگر استفاده میشوند، نیاز به حذف صریح در مخرب را از بین میبرند. در واقع نیازی نیست در مخرب کلاس خود شیءای را که حافظهای را به خود اختصاص داده است به صورت دستی آزاد کنید. علاوه بر این، موجب جلوگیری تولید خطاهای احتمالی از طرف کپی عضوها برای اشیاءای که باید حافظهٔ پویا داشته باشد در کامپایلر نیز میشود. آنها امنترین و توصیه شدهترین روشهایی برای انتقال مالکیت انحصاری، یا بازگشت به یک unique_ptr از یک تابع که شیء ای را در پشته ساخته است و یا با انتقال یکی از آنها به عنوان آرگومانی که در تابع میتواند به عنوان مالکیت بیشتر پذیرفته شود. در هر دو مورد، std::move به طور کلی باید مورد استفاده قرار بگیرد، و این انتقال مالکیت را به صورت صریح بیان میکند. انتقال مالکیت از قبل تعیین شده از طرف توابع امضاء شده معلوم میشود. از نشت حافطه جلوگیری میکند. همچنین، یک شیء unique_ptr میتواند حافظهٔ اختصاص داده شده را با استفاده از new[] مدیریت کند: { std::unique_ptr<int[]> array(new int[123]); DoSomethingWith(array.get()); } به طور معمول توصیه میشود که برای ساخت یک unique_ptr از std::make_unique() استفاده شود. کلاس std::shared_ptr شامل یک اشارهگری است که دارای یک منبع تخصیص حافظهٔ پویا با تفاوت اینکه میتواند چندین شیء را به صورت اشتراکی از یک منبع مشترک ردیابی کند. در واقع هنگامی که موجودیتهای متعددی همان شیء اختصاص یافته شده به حافظه را به اشتراک میگذارند، البته این وضعیت همیشه مشهود نبوده و یا ممکن است آن را به یک مالک واحدی اتخصاص دهید. این اشاره گر های هوشمند، شمارندهای از یک رشتهٔ ایمن(thread-safe) برای منبع حافظهٔ مشترک حفظ میکند و در زمانی که تعداد مرجع آن به صفر رسید، حذف میشود. در واقع این زمانی رخ میدهد که آخرین شیء مشترک از آن حذف شود. تابع use_count() نیز تعداد مراجع را بر میگرداند. همچنین مشابه unique_ptr این شیء یعنی shared_ptr میتواند آرایههای پویا را مدیریت کند که این ویژگی از استاندارد ۱۷ به بعد ممکن شده است. چندین شیء از shared_ptr ممکن است دارای همان شیء باشند. اگر یکی از موارد زیر اتفاق بیفتد، شیء از بین رفته و حافظهٔ آن آزاد میشود: آخرین بازمانده از شیء shared_ptr از بین رفته باشد. آخرین بازماندهٔ شیٔ shared_ptr که دارای یک اشارهگر از طریق اپراتور = و یا reset() است تعیین میشود. آنچه که shared_ptr را از unique_ptr متمایز میکند آن است که آنها میتوانند کپی شوند: { auto age = std::make_shared<int>(30); auto aliasAge = age; age.reset(); } کلاسstd::weak_ptr مانند std::shared_ptr است اما با تفاوت آن که شمارندهٔ آن افزایش نمییابد و اختیار شیء را به دست نمیگیرد. درواقع، بعضی اوقات نیاز است هنگام ساخت مخازنی از اشیاءای که به اشتراک گذاشته شدهاند بدانید آن شیء وجود دارد یا خیر. کاربرد آن نیز همراه با shared_ptr معتبر است و اطلاعاتی در بارهٔ اشیائی که توسط shared_ptr به دست گرفته است ارائه میکند. چند مثال در بارهٔ اشارهگرهای هوشمند: { std::unique_ptr<int> p(new int); // شیء p قابل استفاده در داخل حوزه است. } // در این بخش که خارج از دامنهٔ اشارهگر است حافظهٔ اختصاص یافته آزاد میشود. همانطور که مشخص است یک شیء که تحت اشارهگر هوشمند مورد استفاده قرار میگیرد تا زمانی که خارج از حوزهٔ خود قرار نگیرد قابل استفاده خواهد بود. نمونه کد پایین مثالی از نحوهٔ نمونه سازی تحت اشارهگرهای هوشمند است. void UseSmartPointer() { // Declare a smart pointer on stack and pass it the raw pointer. unique_ptr<Song> song2(new Song(L"Nothing on You", L"Kambiz Asadzadeh")); // Use song2... wstring s = song2->duration_; //... } // song2 is deleted automatically here.
-
1 امتیازبا سلام، با توجه به سوالات مکرر برخی از کاربران و خصوصاً دانشجویان جدید، تصمیم گرفته شد تا توضیحاتی دربارهٔ نحوهٔ یادگیری برنامهنویسی با سیپلاسپلاس بیان شود. قبل از هر چیز لازم است بدانید، سیپلاسپلاس یک زبان برنامهنویسی کاملاً تخصصی مهندسی است. بنابراین یادگیری آن طبیعتاً نیاز به تلاش، تحمل و پشتکار کافی در مقابل چالشهای آن خواهد داشت. مقدمه در حال حاضر بیش از سه دهه است که از ساخت و معرفی زبان برنامهنویسی ++C میگذرد. در رابطه با آن که هدف از ایجاد این زبان چه چیزی بوده و مزایای آن نسبت به زبانهای دیگر چه چیزی است (چرا موتور مخفی جهان مدرن امروزی است) را میتوانید در این مقاله مطالعه کنید. اما بسیاری از افراد علاقهمند به زبانهای برنامهنویسی تمایل بسیاری دارند تا در برنامهنویسی با این زبان به درجه مطلوب و درواقع (حرفهای) برسند. قبل از هر چیز باید مواردی را در نظر داشته باشیم که یاد گیری زبانهای برنامهنویسی به خودی خود کافی نیست! مخصوصاً زبانهای C و ++C مستلزم پیشنیازهای تخصصی بسیاری هستند که در روند تولید، توسعه، تجزیه و تحلیل لایههای مختلف مهم است. آیا زبان سیپلاسپلاس در حال توسعه است؟ به جرأت میتوانم بگویم که سیپلاسپلاس به عنوان پیشتاز زبانهای برنامهنویسی با سرعت بسیار زیادی در حال گسترش و توسعهٔ خود است. بهتر است بدانید این زبان از شیوهٔ نسخهنگاری معمولی بهره نمیبرند، بلکه از «استاندارد» (ISO/IEC) که کمیتهٔ استانداردسازی آن را تأیید و نهایی میکند بهره میبرد. بنابراین، بر اساس استانداردی پیش میرود که پیشنویسهها و بهبودهای آن تماماً با حفظ (پشتیبانی از عقبگرد) قابل توجه است. همانطور که در تصویر مربوطه میبینید، سیپلاسپلاس در آخرین بهروز رسانی، به نقشهٔ توسعهٔ خود در سالهای بعد نیز اشاره کرده است که در قالب استانداردهای ۲۳، ۲۶ و ۲۹ از الآن یاد شدهاند. چیزی که در هیچ زبانی در وضعیت فعلی به صورت نقشهٔ راه از توسعه آنها نمیتوان دید! این خود یک نکتهٔ بسیار مثبت است که تیم (کمیته) استانداردسازی این زبان کاملاً این اطمینان را میدهد که این زبان نسبت به نیاز و آینده در حال به روز بوده، است و خواهد بود. لازم است بدانید، استانداردهای فعلی، ۱۷ و ۲۰ و بعد ۲۳ به عنوان یک نسل انقلابی و جهش یافته از سیپلاسپلاس یاد میشوند، اگر شما تجربهٔ نوینی از برنامهنویسی را میطلبید، بهتر است به استاندارد ۲۰ خوشآمدگویی کنید که در کنار کارآیی بسیار عالی، یک نحو و سبک بسیار ساده و روان در اختیار توسعهدهنده قرار میدهد. در ادامه ما به سوالاتی که معمولاً توسط تازهکاران پرسیده شده است پاسخ دادهایم: ابعاد علمی و اقتصادی کار با ++C در ایران متاسفانه اکثر ما ملتی هستیم، تَنبَل و حاضر برای لُقمهٔ آماده! بنابراین بازار کار در ایران به گونهای است که بیشتر شرکتها و افراد توسعه دهنده به سراغ زبانهای سادهتر و در دسترستر (بی دردسر) میروند. غافل از آن که یک برنامهٔ تولید شده توسط سی++ بسیار سریع، جذاب، قدرتمند و انعطافپذیرتر است. همهٔ بحث در اینجا تمام نمیشود، چرا که شاید در سالهای اخیر وضعیت تقریباً فرق کرده و به کمک اطلاع رسانیهای اساتید و دوستان حرفهای، ما در این زمینه این اطلاعرسانی به خوبی صورت گرفته و توسعه دهندهها از قابلیتها پنهان این زبان آگاه شدهاند و میدانند که سیپلاسپلاس به عنوان یک زبان بسیار کاربردی در زمینههای مختلف جایگاه ویژهای دارد. شرکتها و گروههای برنامهنویسی بسیاری به دنبال برنامهنویسهای سی++ هستند که این امر نشان دهندهٔ این است که نسبت به سالهای گذشته پیشرفت و آگاهی جامعهٔ برنامهنویسی در این حوزه منطقیتر و بهتر شده است. من بارها در مورد بحث محدودیتهای سختافزاری، مشکلات و محدودیتهای پیش و روی قانون مور، مسائل مربوط به انرژی سبز و غیره صحبت کردهام. و اکنون زمان آن رسیده است که بیشتر در این باره فکر کنید که واقعاً چه ابزارهایی آیندهٔ بهتر و موثرتری در پیشرفت صنایع خواهند داشت. بنابراین، بهتر است قبل از هرچیز در نظر داشته باشید که هدف از این تاپیک، این نیست که اثبات کنیم یک زبان نسبت به زبان دیگر برتری دارد. هدف اصلی من این است به واقعیتهایی اشاره کنم که غیر منطقی نیستند. چرا که واقعاً کارفرمایانی وجود دارند که نیازمند به برنامهنویسانی هستند که تخصص خوبی در زبانهای برنامهنویسی دیگری مانند ++C دارند. همه چیز در زبانهای سطحبالاتر خلاصه نشده است! توجه داشته باشید که هدف از این توضیحات چنین نیست که بعد از خواندن این مطالب زبان برنامهنویسی مورد علاقهٔ خود را کنار گذاشته و به سمت سی++ بروید، خیر! یا مقصود آن نیست که با دیدن و شنیدن پیچ و خمهای آن از یادگیری آن منصرف شوید. من بارها گفتهام، تمامی زبانها به عنوان ابزارهای کاری شما در یک جعبهٔ ابزار هستند و هر زبانی حوزهٔ کاربردی خودش را دارد. بنابراین قبل از اینکه شما تصمیم بگیرید که چه زبانی را یاد خواهید گرفت باید حوزهٔ کاری وعلاقهٔ خودتان را مشخص کنید سپس وارد تحقیق و بحث و نظر خواهی راجع به آن زبان نمایید. مقایسهٔ زبان طبق این قانون کاملاً کار اشتباه و بچهگانه است و به هیچ عنوان در مورد یک زبان برنامهنویسی گاردِ تعصبی نگیرید. متاسفانه به خاطر تفکرات اشتباه و معرفیهای غیر منطقی و غیرعلمی برنامهنویسان کشور ما که ممکن است حتی خودِ شما هم چنین تصور کنید، در رابطه با سایر زبانها مانند سی++ بسیاری از کارفرمایان نیازمند چنین برنامهنویسانی هستند که در کشور ما واقعاً نیاز است. توجه داشته باشید که انتخاب درست این نیست که چون همه سراغ زبانهای پر مخاطبتری میروند و چون تمامی آگهیها استخدامی مرتبط با آنها است پس فقط باید آنها را یاد گرفت! خیر چنین تفکری اشتباه است و ضربهٔ بسیار بزرگی در صنعت و دانش آیندهٔ جامعهٔ تخصصی هر کشوری که به این شکل پیش میرود خواهد زد، چرا که ما باید طبق مسیر و سرعتی که دنیا در حال جهش است، خود را هماهنگ و بهروز کنیم. نکاتی در این میان وجود دارد که باید به آنها اشاره کرد: متاسفانه در کشور ما بسیاری از برنامهنویسان چه مبتدی چه حرفهای اینطور تصور میکنند که تولید محصول نرمافزاری یعنی برنامهنویسی یک نرمافزار که قرار است به بانک اطلاعاتی متصل شده و کارهایی مانند ثبت و ویرایش اطلاعات و در نهایت گزارش گیری و دیگر عملیات ممکن را انجام دهد! این تفکر به شدت اشتباه است! الآن دیگر سیستم نرمافزاری، معماریها و سبک و سیاقهای ساختوساز فرق کرده است. مبتنی بودن بر خدمات متمرکز، غیرمتمرکز و دیگر فناوریها بسیار مهم است. توجه کنید که بزرگترین و معروفترین فناوریها مطرح جهانی معمولاً به واسطهٔ این زبان طراحی میشوند، مانند، سیستمعاملها، نرمافزارها، زیرساختها و حتی بلاکچین و بیتکوین که خالی از لطف نیستند. بسیاری از بانکها و شرکتهای صنعتی و اقتصادی مهم کشور نیازمند برنامهنویسان سی++ هستند تا بتوانند در بحث بانکی برای توسعه دستگاههای پرداخت مانند Pos و ATM از این زبان و برنامهنویسان بهره ببرند. در صنایع بزرگ خودرو سازی و دیگر موارد نرمافزارهای مورد نیاز است تا با سرعت بسیار و بدون محدودی پلتفرمی پاسخگوی یک چرخهٔ تولید باشند تا بتواند زیرساختها و رابطهای یک شرکت بزرگ را مدیریت و آن را بهینه کند. در بسیاری از حوزههای صنعتی کشور شرکتهای غولپیکر در زمینهٔ تولیدات انبوه و سنگین که توسط ماشینآلات صورت میگیرد به دنبال برنامهنویسان سی و سی++ هستند که ممکن است به صورت معرف یا آشنا با آنها مواجه و استخدام شوید. شرکتهای سختافزاری و استارتآپهایی که در حوزهٔ الکترونیک و سختافزار فعالیت میکنند به دنبال برنامهنویسیان سی++ هستند تا بتوانند در حوزهٔ کاری خود اهداف خود را توسعه و شما را به عنوان مهرهای مفید پیش ببرند. شرکتهای توسعهدهندهٔ موبایل و خطوط تولیدی تلفنهای همراه داخلی گسترش یافته و به شدت نیازمند برنامهنویسان سی++ هستند که برخی از آنها مبادلات بینالمللی نیز دارند. در بخش حوزهٔ شهر سازی، مدیرت شهر و همچنین راهداری شرکتهایی هستند که برای تولید سیستمهای مدیریتی مانند مدیریت راهها و ترددهای خودرو و یا مدیریت ترافیک و موارد این چنینی به دنبال برنامهنویسان سی++ هستند. بسیاری از شرکتها و حتی تیمهای توسعه بر روی پلتفرمهای iOS و Android به صورت تخصصی سفارشی سازی و حتی ساخت و توسعهٔ اپلیکیشنهای ایرانی تمرکز دارند که جدیداً به لطف آگاهی از فریموُرکهایی مانند Qt به سمت این حوزه آمده و نیازمند سی++ کاران هستند. شرکتهای بازیسازی کشور ما که این سالها با پیشرفتهای خوبی مواجه شدهاند به دنبال برنامهنویسان سی++ هستند که بتوانند در این صنعت برای فرهنگسازی و توسعه صنعت بازی سازی جلو بروند. بسیاری از شرکتهای پنهان وجود دارد که به صورت بسیار مخفیانه در صنایع سهبعدی و پیشرفته در حال فعالیت هستند که محصولات خود را نه در ایران بلکه در خارج از آن آمریکا و دیگر کشورهای اروپایی به فروش میرسانند که به سفارش آنها بوده است. با دید سطحی به این مسائل نباید نگاه کنید، اگر آگهیهای استخدامی نمیبینید به خاطر این است که این زبان کار کُن می خواهد نه تَنبل! بنابراین شما باید به سراغ آن بروید چرا که بسیاری از شرکتهای بینالمللی فعالیتهای بزرگی انجام میدهند که هیچوقت از آنها خبر ندارید و به صورت کاملاً سفارشی و حساسیت کامل به دنبال برنامهنویسان این زبان هستند (چون میدانند یک سی++ کار هدفمند و با دید بازتری به توسعه نگاه میکند). چنین شرکتها معمولاً استخدام را به صورت رابطهای انجام میدهند و تعداشان هم کم نیست. ما میدانیم که شاید شما با دیدگاه اینکه حتماً باید نرمافزارهای کاربردی تولید کنید به قضیه نگاه میکنید، خوشبختانه فریمورک کیوت به قدری قدرتمند و پُخته شده است که میتوان هر محصول کاربردی در هر زمینهای را تولید کرد که از کارایی بسیار بهتری نسبت به دات نت بهرهمند است. در حوزهٔ امنیت، شبکه و موارد این چنینی شرکتهای بزرگ و Ispها نیازمند این زبان هستند. البته دلایل بسیاری وجود دارد که موجب میشود شرکتها از روی ناچاری به سراغ برنامهنویسان دیگر بروند، که من شخصاً آن را تجربه کرده ام ! در بسیاری از پروژهها که به عنوان مشاور فنی در آنها شرکت کرده بودیم متوجه آن شدیم شرکتها به خاطر عدم وجود برنامهنویس سی++ برای ادامهٔ چرخهٔ تولید خود مجبوراً سراغ برنامهنویسهای دیگر زبانها میروند. این امر به خاطر این است که واقعاً درصد تعداد برنامهنویسان این زبان نسبت به زبانهای دیگر به خاطر (راحت طلبی) و شاید عدم آگاهی از این زبان دور هستند. یکی از نکتههایی که اخیراً جالب بوده است، آن است که شما به واسطهٔ سیپلاسپلاس میتوانید حتی وبسایتهای مورد نیاز خود را بسازید! یک سیستم چند-منظوره طراحی کنید که در حوزههای قابل استفاده باشد. برخی از هماهنگیهایی که این زبان خود را به بهروز رسانیهای بسیار سریع در فناوری وفق داده است، پشتیبانی از ساختارهای چند-سکویی و کاملاً بومی با کارآیی بالا است که در حوزههای موبایل، دسکتاپ و وب میتوانید آن را مورد استفاده قرار دهید. از فناوریهای مربوط به فریمورکهای طراحی گرفته، تا امکان ساختوساز در قالب وباسمبلی، بلاکچین و دیگر موارد. یک نکتهٔ بسیار مهم که طی این سالها تجربه کردهام، این است که خیلی از شرکتها و خدمات دهندهها با این که در جریان مزایای این زبان هستند، مجبوراً به خاطر عدم وجود متخصص کافی از ابزارهای دیگر برای توسعهٔ کار خود استفاده میکنند. هرچند مشکلات این زبان تا به الآن شفاف شده است، اما بهروز رسانیها و توسعههای پی در پی آن موجب بهبودهای بسیار چشمگیری در آن نیز شدهاست. برخی از سوالاتی که علاقهمندان به این حوزه میپرسند در ادامه آمده است: من یک دانشجو هستم و رشتهٔ تحصیلی من کامپیوتر است، به برنامهنویسی با ++C علاقه دارم از کجا باید شروع کنم؟ اگر شما به قصدِ حرفهای شدن دنبال یادگیری این زبان هستید، همانطور که اشارهای شد مباحث پیش نیاز برای یادگیری این زبان مهم هستند و برای درک هرچه بیشتر این زبان بهتر است دانش خوبی در زمینهٔ تجزیه و تحلیل رفتار کامپایلر داشته باشید. علاوه بر این برای آشنایی با کامپایلر رفتار سیستمعامل و واکنشهای کامپایلری در سیستمعاملهای متفاوت بسیار مهم است. به عنوان مثال کامپایلر GCC بر روی ایستگاههای یونیکس تعبیه شده و برای خود قوانین و استانداردهایی را دارد. در کنار آن کامپایلر MSVC نوعی کامپایلر اختصاصی تحت ویندوز است که متناسب با ساختار و معماری ویندوز رفتار میکند. در نگاه اول آشنایی با آنها شاید الزامی به نظر نرسد، چرا که شما صرفاً به سمت یادگیری زبان، نحو (سینتکس)، ویژگیها، کتابخانهٔ پیشفرض و هستهٔ آن میپردازید. اما در بُعد ساخت و ساز یک محصول عالی اطلاعات شما در زمینههای مختلف لازم است کافی باشد. من یک دانشجو هستم اما متاسفانه رشتهٔ تحصیلی من کامپیوتر نیست، به برنامهنویسی با ++C علاقه دارم از کجا باید شروع کنم؟ این کار کمی دشوار است، در مرحلهٔ اول پیشنهاد ما این است که سراغ زبانهای برنامهنویسی دیگری بروید که نیازی نداشته باشد شما درگیر درک کامپایلر یا رفتارهای سیستمعاملی شوید. اما به هر حال اگر شما به هر نحوی میخواهید این زبان را یاد بگیرید چارهٔ کار تلاش مستمر و حوصله است. متاسفانه سیپلاسپلاس ذاتی مرموز دارد و آن این است که اگر بتوانید به آن مسلط شوید یک زبان با وفا و قدرتمندی خواهد بود که در هر زمینهای به نیازهای شما پاسخگو خواهد شد. اما اگر به هر دلیلی نتوانید با این زبان دوست شوید به طور بسیار مرموزی اعصابتان را به هم خواهد ریخت ? که البته طبیعی است چون سی++ تحت کامپایلرهای خود دستِ برنامهنویس را آزاد گذاشته و شما هستید که انتخاب میکنید کُد شما به چه شیوهای با توجه به هدف چگونه عمل کند. چقدر زمان لازم است تا من این زبان برنامهنویسی را یاد بگیرم؟ با توجه به ساختار زبان و رفتارهای کامپایلر میتوان گفت به قدری دامنهٔ سی++ گسترده است که تنها راه حل ممکن برای رسیدن به یک وضعیت مطلوب از دانش مرتبط با آن باید زمان مشخصی در نظر گرفته شود. ممکن است شما بتوانید در بازهٔ ۱ الی ۳ ماه مباحث مقدماتی این زبان را درک کنید. اما توجه داشته باشید پیشنیازات آن نیز نیازمند تحقیق، تجربه عملی و نتیجهگیری تئوری و علمی هستند. با توجه به اینکه شما (سریع، هوشمند با گیرایی بالا باشید) میتوانید در کمتر از ۶ ماه به یک پایداری تقریباً قابل قبول در حد مقدماتی این زبان برسید. استاندارد زبان را درک کنید و نحوهٔ برقراری ارتباط با کتابخانههای پیشفرض STL و غیره را تجربه کنید. برای کسب دانش و افزایش آن به میزان متوسط و به بالا نیازمند تلاش بسیار بیشتری خواهید بود که باید در قالب پروژههای عملی و واقعی صورت گیرد. متاسفانه سی++ به دلیل گسترده بودن چنان پیچیدگیهایی را دارد که تنها میتوان در موقع برنامهنویسی به صورت عملی (بر روی پروژههای واقعی) آن را تجربه کرد. آیا ارزش دارد من این زبان را یاد بگیرم؟ فرصت من کم است و میخواهم سریعاً به درآمدزایی برسم در همین ابتدا به شما میگویم که اگر صرفاً به درآمدزایی سریع فکر میکنید، سیپلاسپلاس گزینهٔ مناسبی برای این رویا نیست! اگر شما به عنوان یک برنامهنویس متوسط و به بالا به این زبان تسلط دارید، و حداقل میتوانید با یکی از کتابخانههای خوب آن ارتباط برقرار کنید، وقت آن است که با کتابخانههای قدرتمند این زبان وارد عمل شوید. کتابخانههایی مانند Boost، Poco، Qt و غیره از سری کتابخانههایی میباشد که امکانات بسیاری را در اختیار شما علاقهمندان این زبان قرار میدهند تا بتوانید در کمترین زمان ممکن به نیازهای خود دسترسی داشته و آن را پیاده سازی کنید. همهٔ آنها در ساخت و توسعهٔ محصول به شما کمک میکنند. فراموش نکنید که بارها گفتهام به زبانها، کتابخانهها و فناوریها به عنوان ابزار در داخل جعبهابزار خود بنگرید. توجه داشته باشید که لازمهٔ طراحی و توسعه یک محصول مفید (قابل قبول) در قالب MVP (کمینه محصول پذیرفتنی) مستلزم داشتن دانش طراحی محصول نیز میباشد. اما همه چیز اینگونه خلاصه نشده است و شما برای اینکه بتوانید یک محصول واقعاً قابل قبول را پیاده سازی کنید مسلماً باید آن را مجهز به قابلیتهای دیگری مانند منابع ذخیره داده و یا سرویسها و ماژولهایی کنید که بتواند به عنوان یک محصول کاربردی روی آن حساب کرد. آیا صرفاً با دانستن زبانهای برنامهنویسی و تسلط بر آن میتواند یک محصول استاندارد و سطح جهانی را به طور کامل تولید کرد؟ نظر من قطعاً خیر است! اگر شما واقعاً با دیدگاه یک سازنده، یک تولید کننده و مهندس تمام عیار در ذهن خود رویا پروری میکنید، در این صورت باید بدانید همه چیز در زبان خلاصه نمیشود! از نظر من حداقل مواردی که (به طور خیلی خیلی خلاصه و محدود) نیاز است تا یک متخصص بتواند پاسخگوی تصمیمگیری نقشهٔ توسعهٔ یک محصول برای مشتری در ابعاد مختلف و سطوح متفاوت از حوزههای موجود در قالب اصولی باشد به صورت زیر است که فرد یا یک تیم باید به آنها اشراف کافی داشته باشد: ۱- آشنا مبانی کامپیوتر که امر طبیعی (شامل درک و فهم مسائل و نحوهٔ حلشون متناسب با پلتفرم اجرایی محصول) ۲- آشنا به ساختار نوع محصول استاندارد در یک حوزه مثل: وب، آیاواس، اندروید یا دسکتاپهای مختلف مثل لینوکس، مک و ویندوز، اینترنت اشیاء و دیگر موارد. ۳- آشنا به فلسفهٔ بکاند و فرانتاند یا ترکیبی از این دو به همراه ابزارهای مناسب. ۴- آشنا به اصول طراحی UI/UX به عنوان یک نیاز و یک فاکتور مهم در ساخت محصولی که وابسته به عملکرد کاربر دارد و در حوزهٔ فرانتاند مهم و کاربردی هست. ۵- آشنا به اصول SOLID و امثالش مهم هستند. ۶- آشنا اصول برنامهریزی ساخت بانک اطلاعاتی، اینکه از چه بانک اطلاعاتیای استفاده کنی و چرا؟ ۷- آشنا به ارتباطات دادهای، جداول و ارتباط بین فیلدها، جداول و روشهای درست تبادل اطلاعات مابینی دادهها. ۸- آشنا و تسلط کافی به یک محیط توسعه و ادغام ابزارها و محیط طراحی برای هدف. ۹- آشنا به معماری ساختار و رابطهای برنامهنویسی (Api) ۱۰- آشنا به استانداردهای Http، درک و مدیریت درخواست، پاسخها و ... ۱۱- آشنا به الگوهای طراحی برنامهنویسی (DP) ۱۲- آشنا به روشهای نگهداری و آزمایش نرمافزار و کدها به خصوص درک مبحث Fault tolerance. ۱۳- آشنا به روشهای اطمینانسازی و ایمنسازی پردازشهای داخلی نرمافزار برای جلوگیری یا دشوار سازی نفوز و خرابکاری. ۱۴- آشنا به روشها و معماریهای احراز هویت و نحوهٔ ادغامش با نرمافزار مثل:JWT, OAuth, AWS و غیره... ۱۵- آشنا به نوع پارادایمهای زبان برنامهنویسی، در قالبهای (دستوری) Imperative و (اعلانی) Declarative مثل OOP، functional و دیگر موارد. ۱۶- آشنا به سبک معماری نرمافزاری (Microservice یا مثلاً Monolith) مزایا و معایب آنها. ۱۷- آشنا به سبک معماری طراحی مانند MVC در طراحی بدنهٔ محصول. ۱۸- آشنا به سبک و الگوهای طراحی ساختاری در بکاند مانند Builder، Abstract، Factory و غیره. ۱۹- آشنا به ساختار یک زبان (در صورتی که میخواهید جوابگوی مسائلِ پیش آمده باشید) کالبدشکافی زیرپوستی و عمیق یک زبان مهم است. ۲۰- آشنا و درک کامپایلرها و مفسرها، تفاوتها و شیوههای عملکردیشون نسبت به کدهای بهینه شده و عادی. ۲۱- آشنا و درک مدلهای مختلفی از سیستمهای توزیع شده مثل IaaS، PaaS، SaaS یا FaaS. ۲۲- آشنا به ابزارهای ساخت و فرآیند کاری اونها مثل CMake، NMake، QMake و غیره. ۲۳- آشنا به روشهای مدیریت وابستگیهای نرمافزار و ابزارهای لازم برای بستهبندی بهتر خروجی. ۲۴- آشنا به روشهای کدنویسی قابل آزمایش (Unit Test) و استفاده از ابزارهایی مثل CTest, GTest, Catch2 و غیره. ۲۵- آشنا به توسعهٔ آزمون محور (Test Driven- Development) ۲۶- آشنا به گامها و شرایط نسخهنگاری و مراحل توسعهٔ نرمافزار (SDP) ۲۷- آشنا به روشهای امنیت در کد و توسعه به شیوههای بررسی از طریق Fuzz-Test، Sanitizer، آنالیزرهای پویا و ایستا و غیره... ۲۸-آشنا به قوائد طراحی بر پایهٔ خدمات مبتدی بر معماری ابری برای خدمات پیامی، وبسرویسها، پردازش و غیره. ۲۹- در سطوح وب آشنا به مکانیزم شاخص بندی، فاکتورهای SEO و شیوههای درست بهبود صفحات وب. ۳۰- آشنا به روشهای به کار گیری و پیادهسازی ثبت کنندهٔ وقایع در دل محصول و روشهای بازخورد برای توسعهٔ بهتر به همراه مانیتورینگ، نظارت و تریسینگ. ۳۱- در شرایط لزوم آشنا به نحوهٔ به کار گیری و دلیل استفاده از فناوریهایی مثل Redis، Memcached و غیره. ۳۲- آشنا و درک صحیح از مفاهیم همزمانی (Concurrency) و روشهای به کار گیری آن نسبت به زبان برنامهنویسی و شرایط مناسب استفاده. ۳۳- آشنا به سبک و قوائد و ساختار زبانهای برنامهنویسی و فرآیند ساخت و ترجمه. ۳۴- و تا صدها گزینهٔ دیگر که میتوان در این بخش لیست کرد که اگر انتخاب شما زبانهای نزدیک به سیستم باشد این داستان در ادامهٔ این توضیحات سر به فلک خواهد کشید. با توجه به این موارد اگر بخواهید محصولی را بسازید که طبق استاندارد آن را توسعه و تولید کنید که در بستر سیپلاسپلاس شکل میگیرد، باید ابزارها و موارد پیشنهادی زیر را در اختیار داشته باشید و کار با آنها را تا حد نیاز بدانید: یک محیط توسعه یکپارچهٔ نرمافزار مانند Qt Creator، Xcode یا Visual Studio (پیشنهاد ما Qt Creator است) این محیط به عنوان IDE نیز یاد میشود. پلتفرم توسعه (سیستمعاملی) که قرار است محیط توسعهٔ یکپارچه خود را بر روی آن نصب و شروع به برنامهنویسی کنید را مشخص نمایید. اگر شما کاربر ویندوز هستید باید محیط توسعهٔ یکپارچهٔ شما مجهز به کامپایلر MSVC و یا نسخهٔ پورت شدهٔ GCC یعنی MinGW باشد. اگر شما کاربر مکاواِس هستید به صورت پیشفرض با نصب محیط توسعه کامپایلر Clang بر روی آن تعبیه خواهد شد. البته میتوانید به صورت سفارشی از کامپایلر GCC نیز استفاده کنید. در صورتی که کاربر لینوکس هستید کامپایلر GCC به صورت پیشفرض بر روی محیط توسعهی شما تعبیه خواهد شد. آشنا به دستورات ترمینال و یا کنسول در سیستمعاملهای لینوکس، مک و ویندوز در ساخت و سازهای دستوری مفید هستند و نیاز است آنها را بدانید. آشنا به Git و دستورات مربوط به آن در نگهداری و به اشتراکگذاری مخازن پروژه میتواند برای شما سودمند باشد. بر اساس پیشنها جهت محیط توسعه کتابخانهٔ Qt نیز پیشنهاد میشود (دلیل آن این است که این کتابخانه به شما کمک میکند تا بتوانید رابط کاربری نرمافزار (محصول) خود را پیاده سازی کنید). اگر هدف شما طراحی یک محصول استانداردی است که از شکل و ظاهر آنچنانی برخوردارد نیست بهتر است از ماژولهای پیشفرض Qt مانند Qt Widget برای طراحی آن استفاده کنید. این کار بسیار ساده است و نیازی برای داشتن دانش در رابطه با حوزههای JavaScript و QML ندارد. البته میتوانید با ترکیب CSS طراحی رابط کاربری برنامهٔ خود را بهبود ببخشید. بعد از این موارد نیاز است که شما هدف توسعهٔ خود را مشخص کنید، اینکه میخواهید توسعه دهندهٔ چه پلتفرمی باشید؟ تولید کننده برنامههای دسکتاپ بر روی ویندوز؟ یا لینوکس و مک؟ یا همهٔ آنها؟ خوشبختانه با توجه به قابلیتهای ذاتی سی++ و کیوت شما میتوانید برنامهٔ خود را تنها با داشتن محیط توسعهٔ خود بر روی پلتفرم مورد نظر خود کامپایل و خروجی بگیرید (البته به شرط اینکه از سرویسهای اختصاصی سیستمعاملی) استفاده نکرده باشید. البته دقت کنید اگر شما توسعهدهندهٔ اختصاصی برای فقط یک سیستمعامل خواهید بود، در این صورت نیازی به یادگیری مفاهیم یا رابطهای اختصاصی برنامهنویسی یک پلتفرم دیگر نخواهید بود. اگر مشتاق آن هستید که برای پلتفرمهای موبایل مانند آیاواس یا اندروید برنامه تولید کنید، موضوع کمی گستردهتر خواهد شد و حتماً باید ملزوماتی که در ابتدای مقاله به آن اشاره شده است را در نظر داشته باشید. برای مثال تولید یک نرمافزار iOS مستلزم آن است که شما علاوه بر داشتن دانش سی++ در رابطه با معماری و ساختار و همچنین قوانین، قوائد و ساختار نرمافزارهای مرتبط با اپل راداشته باشید. در Android نیز این چنین است. اگر شما تازه کار هستید پیشنهاد میکنیم هدف خود را فعلاً محدود بر یک پلتفرم خاص کنید، حتماً نیاز نیست اطلاعات خود را کامل و سپس اقدام کنید. برای مثال توسعه محصول بر روی ویندوز برای آغاز کار بسیار مناسب است و شما صرفاً بر روی این پلتفرم متمرکز خواهید بود. در نهایت شما محصول خود را با آزمایش وخطاهای بسیاری میتوانید تولید و با توجه به مستنداتی که در همین مرجع ارائه شده اس مستقر و برای کاربر نهایی ارائه کنید. برای اینکه بدانید مزایای این زبان در چیست و چه کتابخانههایی میتوانند مفید باشد و برخی از سوالات احتمالی که ممکن است به ذهن شما برسد این بخش را مطالعه کنید. برای نحوهٔ شروع کار با Qt این بخش را مطالعه کنید. جهت نحوهٔ نصب و راه اندازی محیط توسعه این بخش را مطالعه کنید. منابع فارسی یا زبان اصلی؟ پاسخ این سوأل بدون شک راحت است! زبان انگلیسی، زبان علم است، بنابراین هر آنچه که شما در زبانهای بومی و غیر انگلیسی مطالبه میکنید، ممکن است با محدودیتهای شدیدی مواجه شوید. بنابراین برای یادگیری محتوای علمی به شدت توصیه میشود به کمک مراجع انگلیسی آن را بیاموزید! من زبانم ضعیف هست، آیا باید به زبان انگلیسی تسلط کافی داشه باشم تا بتوانم زبانهای برنامهنویسی را یاد بگیرم؟ این یکی از سوألهای بسیار پر تکرار است که بارها با آن مواجه میشویم! در پاسخ باید صادقانه بگویم، شما به حداقلهای زبان انگلیسی واقعاً نیاز دارید! در حد این که متنهای عادی را بخوانید، آنها را متوجه باشید و بر اساس نگارش معنای صحیح جمله و واژهها را درک کنید. رفته رفته به آن عادت خواهید کرد و در آن نیز حرفهای خواهید شد. اما فراموش نکنید که زبانآموزی در کنار برنامهنویسی از لزومات است. در مورد واژههای تخصصی هم نگران نباشید، معمولاً واژههایی که معنای آنها را مابین جملات و کتابها نمیدانید، در مراجع و یا پانویسهای آنها تعریف میکنند. بسیاری از واژهها در قالب یک روش، مفهوم یا اصطلاح عنوان میشوند و شما باید به دنبال تعریف کامل آن باشید. به عنوان مثل، اصطلاح RAII در سیپلاسپلاس که به برخی از آنها در این بخش اشاره کردهام. من سن پایینی ندارم، آیا برای شروع کردن برای یادگیری سیپلاسپلاس دیر است؟ شاید من تجربهٔ سنیِ کافی، نسبت به کسانی که این سوأل را میپرسند نداشته باشم، اما نسبت به تجربهای که در مهندسی کامپیوتر و به خصوص ساختوساز و توسعهٔ محصولات نرمافزاری دارم، میتوانم به جرأت بگویم که این یک دغدغهٔ ذهنیای به حساب میآید که شاید در قالب و جنسِ ترسِ بیهوده از دست دادن زمان را به خود بگیرید. اما واقعیت آن است، تا زمانی که شما شروع نکنید، بله نمیتوانید! اما نکتهای که مد نظرم است بدانید، این است که در انتخاب زبانها، به خصوصی یادگیری سیپلاسپلاس، بهتر است بخشی از هدف و استعدادی که به آن دارید را هدف قرار دهید، (هدف مشخص و شفافی داشته باشید) چون خاصیت این زبان در چند-منظوره بودن آن است، و ممکن است شما را وسوسهٔ خود در همهٔ جوانب کند! که این باعث میشود شما هرگز به یک نقطهٔ شروع نرسید. به عنوان مثال، برای شروع بهتر است یک حوزه را انتخاب کنید و پیشبرورید، مانند: برنامهنویسی و طراحی اپلیکیشن در سیستمعامل ویندوز. یا برنامهنویسی در حوزهٔ موبایل، وب، بازیسازی، امبدها (سیستمهای درونسازی شده) و غیره... این بستگی به سلیقهٔ شما و نوع نیازی که در بازار میبینید خواهد داشت. در زیر منابعی را معرفی میکنم که به رایگان یا با کمترین هزینه میتوانید به آنها دسترسی داشته باشید: منابع استاندارد و رسمی زبان سیپلاسپلاس: https://en.cppreference.com https://isocpp.org برای یادگیری در سطوح مقدماتی وبسایتهای زیر پیشنهادات مناسبی هستند: https://www.geeksforgeeks.org/references-in-c http://www.cplusplus.com/reference https://www.tutorialspoint.com/cplusplus/cpp_references.htm https://www.learncpp.com در صورتی که میخواهید در حالت بسیار ساده، تصویری و در قالب برگههای تقلب به ویژگیهای زبان و کتابخانههای آن بپردازید، وبسایت زیر یک نمونه بسیار مناسب است: https://hackingcpp.com توجه کنید که خیلی از مباحث در وبسایتها ذکر نمیشود، نیاز است بعضی از کتابها را در نظر بگیرید و آنها را عمیقاً مطالعه کنید، بنابراین برای مطالعه به ترتیب سطح مقدماتی و پیشرفته را در زیر عنوان میکنم: Beginning C++ Programming Beginning C++20 A Tour of C++ The C++ Programming Language C++ Primer Programming: Principles and Practice Using C++ کتابهای معرفی شده به استانداردهای ۱۱، ۱۴، ۱۷ و ۲۰ اشاره میکنند. کتابهای پیشنهادی برای سطح پیشرفته: Effective C++ Professional C++ C++ Templates: The Complete Guide – Second Edition Modern C++ Programming Cookbook Hands-On System Programming with C++۱۷ C++ High Performance Optimized C++ در صورتی که نیاز به کسب دانش بیشتر در حوزهٔ سطح پایین، سختافزار، معماری و ساختارهای نرمافزاری دارید کتابهای زیر بسیار مفید هستند: Computer Organization & Design RISC-V / ARM / MIPS / x86 Software Architecture with C++ در صورتی که تجربیات و نوشتههای خودم رو در این باره نیاز دارید به صورت زیر دستهبندی کردم که به ترتیب پیشنهاد میکنم مطالعشون کنید: اگر به دنبال مشاورهها، منابع یا مقالات و توصیههای فارسی یا انگلیسی من هستید، پیشنهاد میکنم در همین وبسایت، یوتیوب، گیتهاب و یا کانال تلگرامی من ملحق بشید. من هر جا که باشم، با شناسهٔ KambizAsadzadeh اگر در حد توانم باشد شما را راهنمایی خواهم کرد.
-
1 امتیازکتابخانهی اوپن سی اِل مخفف Open Computing Language بستری برای برنامههایی که قرار است بر سکوهای ناهمگن یا تکیه بر پردازندههای مرکزی و پردازندههای گرافیکی و سایر پردازندهها اجرا شوند. این کتابخانه دارای یک زبان بر پایهی C99 و C++11 برای نوشتن کرنلها و همچنین رابطهای برنامهنویسی برای تعریف و پس از کنترل بستر استفاده شوند را دارا است. این کتابخانه چندپردازندگی را با استفاده از روشهای وظیفه محور (Task-Based) و داده محور (Data-Based) پشتیبانی میکند. اوپن سی اِل توسط هر دو شرکت AMD/ATI و Nvidia پذیرفته شده است. در طراحی اوپن سی اِل، مقدار زیادی از رابطههای پردازشی با Cuda و رقیب آن، مایکروسافت دایرکت کامپیوت (Direct-Compute) به اشتراک گذاشته شده است. پیاده سازیهای مربوطه از طرف Altea, AMD, Apple صورت گرفته شده است که در این میان OpenCL همراه با OpenGL به نفع Metal2 منسوخ شده اند. همچنین IBM, Imagination, Intel, Nvidia, Qualcomm, Samsung, Vivante, Xilinx و Ziilabs آن را پذیرفتهاند. این کتابخانه یکی از قدرتمند ترین پلتفرمهای موجود در بازار در مقابل DirectX میباشد گه از سوی کمیتهی Khronos Group اعلام شده است که پا به پای DirectX ه فعالیتش ادامه میدهد. جالب است بدانید نسخههای جدید این کتابخانه با قدرت بسیار زیادی بر روی PS4 و PS4 Pro استفاده میشوند. از آنجایی که PS4 از معماری GCN استفاده میکند، قابلیت پشتیبانی از DiectX 12 نیز برای آن فراهم شده است. بهتر است بدانید توسعه اصلی این پلتفرم توسط اپل انجام شده است که در حال حاضر توسط کمیتهی Khronos Group اداره میشود که بر روی طیف وسیعی از سخت افزارهای روز و کارت گرافیکیهای محتلف گرفته تا پردازندههای موجود پشتیبانی میشود. قدرت روز افزون اوپن سی اِل در حال افزایش است و شاید اگر قدرت و سرمایهی مایکروسافت نبود، OpenCL سلطان بی چون و چرای بازار میشد. کودا با وجود انکار انویدیا، فریم ورکی است اختصاصی که در بسیاری از محصولات مورد استفاده قرار میگیرد. انویدیا تلاش میکند رقبایش را به استفاده از کودا وادار کند، اما تلاشش نتیجه بخش نبوده و میبینم که از این فریم ورک بیشتر در توسعه محصولات خودش استفاده میشود. از طرفی میتوان ادعا کرد که Direct Compute هم اختصای است. چون فقط بر روی ویندوز و دایرکت اِکس ۱۱ به بالا اجرا میشود. اما OpenCL منبع باز است و بسیاری از شرکتهای بزرک از جمله Nvidia از آن پشتیبانی میکنند. جهت نصب و راه اندازی این کتابخانه برای پردازندههای Intel به این بخش مراجعه کرده و نسخهی Amd را در این بخش و برای Nvidia از این صفحه دریافت و استخراج نمایید. این کتابخانه در قالب SDK شامل include و lib تحت تو معماری x86 و x64 میباشد که باید در محیط توسعهی نرمافزاری خود آن را معرفی کنید. در محیط Qt Creator طبق آموزشهای قبل اقدام کنید. با توجه به اینکه ما SDK مربوطه را در مسیر C:/IntelOpenCL/sdk استخراج کردهایم، کُد فایل .pro به صورت زیر خواهد بود: LIBS += -L$$PWD/../../../../../Intel/OpenCL/sdk/lib/x86/ -lOpenCL INCLUDEPATH += $$PWD/../../../../../Intel/OpenCL/sdk/include DEPENDPATH += $$PWD/../../../../../Intel/OpenCL/sdk/include جهت آزمایش عملکرد کتابخانه توجه داشته باشید که فایلهای هدر در پلتفرم macOS در پوشهی OpenCL و در محیطهای ویندوز و لینوکس در مسیر CL موجود میباشند. #ifdef __APPLE__ #include <OpenCL/opencl.h> #else #include <CL/cl.hpp> #endif در ادامه کد زیر نتیجهی جمع دو آرایه با یکدیگر را تحت OpenCL اجرا خواهد گرد: #include <iostream> #include <vector> #ifdef __APPLE__ #include <OpenCL/opencl.h> #else #include <CL/cl.hpp> #include <CL/opencl.h> #endif using namespace std; int main(){ //get all platforms (drivers) std::vector<cl::Platform> all_platforms; cl::Platform::get(&all_platforms); if(all_platforms.size()==0){ std::cout<<" No platforms found. Check OpenCL installation!\n"; exit(1); } cl::Platform default_platform=all_platforms[0]; std::cout << "Using platform: "<<default_platform.getInfo<CL_PLATFORM_NAME>()<<"\n"; //get default device of the default platform std::vector<cl::Device> all_devices; default_platform.getDevices(CL_DEVICE_TYPE_ALL, &all_devices); if(all_devices.size()==0){ std::cout<<" No devices found. Check OpenCL installation!\n"; exit(1); } cl::Device default_device=all_devices[0]; std::cout<< "Using device: "<<default_device.getInfo<CL_DEVICE_NAME>()<<"\n"; cl::Context context({default_device}); cl::Program::Sources sources; // kernel calculates for each element C=A+B std::string kernel_code= " void kernel simple_add(global const int* A, global const int* B, global int* C){ " " C[get_global_id(0)]=A[get_global_id(0)]+B[get_global_id(0)]; " " } "; sources.push_back({kernel_code.c_str(),kernel_code.length()}); cl::Program program(context,sources); if(program.build({default_device})!=CL_SUCCESS){ std::cout<<" Error building: "<<program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(default_device)<<"\n"; exit(1); } // create buffers on the device cl::Buffer buffer_A(context,CL_MEM_READ_WRITE,sizeof(int)*10); cl::Buffer buffer_B(context,CL_MEM_READ_WRITE,sizeof(int)*10); cl::Buffer buffer_C(context,CL_MEM_READ_WRITE,sizeof(int)*10); int A[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int B[] = {0, 1, 2, 0, 1, 2, 0, 1, 2, 0}; //create queue to which we will push commands for the device. cl::CommandQueue queue(context,default_device); //write arrays A and B to the device queue.enqueueWriteBuffer(buffer_A,CL_TRUE,0,sizeof(int)*10,A); queue.enqueueWriteBuffer(buffer_B,CL_TRUE,0,sizeof(int)*10,B); //run the kernel //alternative way to run the kernel cl::Kernel kernel_add=cl::Kernel(program,"simple_add"); kernel_add.setArg(0,buffer_A); kernel_add.setArg(1,buffer_B); kernel_add.setArg(2,buffer_C); queue.enqueueNDRangeKernel(kernel_add,cl::NullRange,cl::NDRange(10),cl::NullRange); queue.finish(); int C[10]; //read result C from the device to array C queue.enqueueReadBuffer(buffer_C,CL_TRUE,0,sizeof(int)*10,C); std::cout<<" result: \n"; for(int i=0;i<10;i++){ std::cout<<C[i]<<" "; } return 0; } نتیجه خروجی جمع دو آرایه با یکدیگر و همچنین شناسایی پلتفرمهای قابل پشتیبانی در OpenCL: Using platform: Intel(R) OpenCL Using device: Intel(R) HD Graphics 4400 result: 02435768109
-
1 امتیازجزئیات در ++C ویرایش ۱۷: کد نویسی ساده با توجه به مشخصاتی که در استاندارد ISO/IEC 14882:2017 که ارائه شده است، ویژگیهای جدید برای این معرفی میشوند تا کد شما تمیز تر و بهتر و در کل رَساتر اعمال شوند. این مقاله را برای مطلع شدن از جزئیات بیشتر بخوانید. سیپلاسپلاس ۱۷ چندین ویژگی بزرگ زبان را ارائه میدهد که باعث میشود کد ما زیباتر و بهتر شود. بنابراین بیایید باهم یک نگاهی به این ویژگیها داشته باشیم. ممکن است شما بگویید که بیشترین ویژگیهای جدید زبان (به جز پیشرفت های کتابخانه استاندارد - STL) برای نوشتن کد ساده تر و پاکتر میباشند. با توجه به مجموعه جزئیات سیپلاسپلاس ۱۷ که بسیاری از چیزهای بزرگ را مورد بررسی قرار داده است، ما امروز تنها برای بعضی از ویژگی ها که از داخل این مجموعه عظیم بیرون کشیدهایم اشاره خواهیم داشت که باعث میشود کد شما فشردهتر و بهینه تر شود. پیوندهای ساخت یافته / اعلانهای تجزیه عبارت Init-statement برای if/switch متغیرهای درون خطی (inline) شرط constexpr if و چند موارد دیگر پیوندهای ساخت یافته، آیا اغلب با tuple ها کار کردهاید؟ اگر نه، پس احتمالاً باید به آن نگاهی کنید. tuple ها تنها برای بازگشت مقادیر چند گانه از یک تابع پیشنهاد نمیشوند، آنها پشتیبانی ویژگیای از زبان را داشتند. به طوری که باعث میشود کد ساده تر و پاکتر شود. برای مثال (std::tie که از مرجع اصلی سیپلاسپلاس به دست آمده است) به صورت زیر است: std::set<S> mySet; S value{42, "Test", 3.14}; std::set<S>::iterator iter; bool inserted; // unpacks the return val of insert into iter and inserted std::tie(iter, inserted) = mySet.insert(value); if (inserted) std::cout << "Value was inserted\n"; توجه داشته باشید که باید iter و inserted را ابتدا وارد کرده باشید. سپس شما میتوانید از std::tie استفاده کنید. با این حال این بخش کوچکی از کد نمونه است: std::set<S> mySet; S value{42, "Test", 3.14}; auto [iter, inserted] = mySet.insert(value); اینجا توجه داشته باشید که یک خط به جای سه خط جایگزین شده است! این کد سادهتر و خواناتر و درعین حال ایمن تر است، اینطور نیست؟ همچنین، شما هم اکنون میتوانید از const استفاده کنید و آن را به صورت const auto [iter inserted] بنویسید که صحیح است. پیوند ساختاری تنها به tuple ها ختم نمیشود، چرا که ما سه مورد دیگر را داریم: اگر مقدار دهی اولیه یک آرایه باشد: // works with arrays: double myArray[3] = { 1.0, 2.0, 3.0 }; auto [a, b, c] = myArray; اگر مقدار دهی اولیه std::tuple_size<> را پشتیبانی کند و تابع get را فراهم کند که شایع ترین مورد است. auto [a, b] = myPair; // binds myPair.first/second به عبارت دیگر، شما میتوانید کلاسهای خود را پشتیبانی کنید، با فرض این که شما تابع get را در پیاده سازی رابط کلاس خود اضافه کرده باشید. اگر مقدار دهی اولیه فقط شامل اعضای عمومی شود در این صورت: struct S { int x1 : 2; volatile double y1; }; S f(); const auto [ x, y ] = f(); در حال حاضر این روش برای دریافت یک مرجع از یک عضو tuple آسان است. auto& [ refA, refB, refC, refD ] = myTuple; و یکی از جالبترین استفادهها (پشتیبانی از حلقهها است): std::map myMap; for (const auto & [k,v] : myMap) { // k - key // v - value } پیوند ساختاری یا تقسیم بندی اعلانها برای این ویژگی، ممکن است شما نام های دیگری را دیده باشید، "اعلان تجزیه". همانطور که میبینیم، این دو نام در نظر گرفته شده است، اما فعلاً استاندارد سازی در حالت پیشنویسه است و با نام "پیوندهای ساختاری" میباشند. جزئیات بیشتر در رابطه با این مورد در اسناد P0217R3، P0144R0 و P0615R0 موجود هستند. همچنین این مورد با کامپایلرهای GCC 7.0،MSVC2017 و Clang 4.0 سازگار است. عبارت Init-statement برای if/switch نسخه جدید عبارت شرطی if و switch در سیپلاسپلاس جدید به صورت زیر است: if (init; condition) , switch (init; condition) قبلاً باید به صورت زیر مینوشتیم: { auto val = GetValue(); if (condition(val)) // on success else // on false... } در اینجا val یک دامنه جدا کننده بدون دارد که باعث "نشت - فقدان" در خاتمه دهنده دامنه خواهد شد. در حالی که شما در نسخه جدید میتوانید به صورت زیر بنویسید: if (auto val = GetValue(); condition(val)) // on success else // on false... متغیر val تنها در داخل عبارات if و else قابل رویت است، بنابراین آن یک "نَشت" نخواهد داشت. condition ممکن است چندین عبارت باشد نه تنها if بنابراین متغیر val یکی از دو مقدار true/false را خواهد داشت. چرا این ویژگی کاربرد دارد؟ اجازه دهید تا به شما بگوییم زمانی که میخواهید چندین چیز را در یک رشته را جستجو کنید به صورت زیر خواهید داشت: const std::string myString = "My Hello World Wow"; const auto it = myString.find("Hello"); if (it != std::string::npos) std::cout << it << " Hello\n" const auto it2 = myString.find("World"); if (it2 != std::string::npos) std::cout << it2 << " World\n" ما باید از نامهای مختلفی برای it استفاده کنیم و یا اینکه آن را با دامنه خاتمه دهنده جدا سازیم. { const auto it = myString.find("Hello"); if (it != std::string::npos) std::cout << it << " Hello\n" } { const auto it = myString.find("World"); if (it != std::string::npos) std::cout << it << " World\n" } عبارت جدید شرطی if در نسخه جدید یک دامنه اضافه را در یک خط ایجاد میکند. if (const auto it = myString.find("Hello"); it != std::string::npos) std::cout << it << " Hello\n"; if (const auto it = myString.find("World"); it != std::string::npos) std::cout << it << " World\n"; همانطور که قبلاً اشاره شده است، متغیر تعریف شده در عبارت شرطی if در بلوک دیگری قابل مشاهده است. بنابراین شما میتواین به صورت زیر بنویسید: if (const auto it = myString.find("World"); it != std::string::npos) std::cout << it << " World\n"; else std::cout << it << " not found!!\n"; به علاوه، شما میتوانید آن را با پیوند ساختاری بر اساس کد نمونه از جانب (Herb Sutter) استفاده کنید: // better together: structured bindings + if initializer if (auto [iter, succeeded] = mymap.insert(value); succeeded) { use(iter); // ok // ... } // iter and succeeded are destroyed here جزئیات بیشتر در اسناد زیر آمده است: سند P0305R1 ویدیو موجود در یوتیوب با عنوان (C++ Weekly - Ep 21 C++17’s if and switch Init Statements) این مورد با کامپایلرهای GCC 7.0،MSVC-2017.3 و Clang 3.9 سازگار است. متغیرهای درون خطی (inline) با شروع مقدار دهی دادههای غیر استاتیک، اکنون میتوانیم یک متغیر عضو را دی یک مکان اعلام کنیم. با این حال، با متغیرهای استاتیک یا const static، معمولاً باید آن را در برخی از فایلهای cpp تعریف کنید. در سیپلاسپلاس ۱۱ و کلید واژه constexpr که مارا قادر میسازد تا در یک مکان اعلان و تعریف متغیرهای استاتیک را انجام دهیم، اما این امکان تنها به constexpr محدود میشود. قبلاً فقط روشها/توابع میتوانستند به عنوان inline تعریف شوند، حالا شما میتوانید این کار را با متغیر ها در داخل فایل هدر انجام دهید. یک متغیر اعلام شده درون خطی معنای مشاهبی دارد بنابراین همانند یک تابع inline تعریف میشود. آن را میتوان به واحدهای ترجمه چند گانه نیز تعریف کرد. مثالهای زیر را ببینید: struct MyClass { static const int sValue; }; inline int const MyClass::sValue = 777; و حتی struct MyClass { inline static const int sValue = 777; }; همچنین توجه داشته باشید که متغیرهای constexpr به طور ضمنی inline هستند، بنابراین نیازی به استفاده به صورت constepr inline myVar = 10; نمیباشد. این ویژگی چرا کد را ساده تر میکند؟ برای مثال، تعداد زیادی از هدرها در کتابخانه تنها تعدادی از روش های (هک) را محدود میکنند (مانند استفاده توابع درون خطیinline و یا قالب ها) و در نهایت مزیت constexpr این است که مقدار دهی اولیه شما نباید constexpr باشد. جزئیات بیشتر در رابطه با این ویژگی در سند زیر موجود است: سند P0386R2 این مورد با کامپایلرهای GCC 7.0 و Clang 3.9 سازگار است اما فعلاً با MSVC سازگاری ندارد. ویژگی مربوط به constexpr if ممکن است در بعضی جاها به قابلیت std::enable_if در سیپلاسپلاس ۱۴ نگاه کنید که آن به راحتی با constexpr if جایگزین میشود. بنابراین، در اکثر موارد، ما اکنون میتوانیم تنها با نوشتن عبارت یک constexpr if این کار را بهتر و تمیز تر انجام دهیم. این ویژگی برای برنامه نویسی metaprogramming/template بسیار مهم است که احتمالاً طبیعت آن بسیار پیچیده خواهد بود. یک مثال ساده با تابع Fibonacci: template<int N> constexpr int fibonacci() { return fibonacci<N-1>() + fibonacci<N-2>(); } template<> constexpr int fibonacci<1>() { return 1; } template<> constexpr int fibonacci<0>() { return 0; } حال میتوان آن را تقریباً در یک حالت نرمال (نسخه بدون کامپایل) نوشت: template<int N> constexpr int fibonacci() { if constexpr (N>=2) return fibonacci<N-1>() + fibonacci<N-2>(); else return N; } در رویداد ۱۸ هم جلسات هفتگی سیپلاسپلاس در جیسون ترنر نمونهای را میتوان یافت که در آن عبارت constexpr if هیچ منطق اتصال کوتاهی را در زمان کامپایل انجام نمیدهد، بنابراین این کد باید کامپایل شود: if constexpr (std::is_integral<T>::value && std::numeric_limits<T>::min() < 10) { } در کد فوق برای T شما در std::string خطایی کامپایل را دریافت خواهید کرد زیرا numeric_limits برای رشته ها تعریف نشده اند. در جلسات C++NOW 2017 آقای Bryce Leblbach با عنوان جلسه خود C++17 Features در ۱۶ دقیقه مثال بسیار زیبایی را در رابطه باconstexpr if زد که میتواند برای تابع get استفاده شود که آن برای پیوند ساختاری مورد استفاده قرار میگیرد. struct S { int n; std::string s; float d; }; template <std::size_t I> auto& get(S& s) { if constexpr (I == 0) return s.n; else if constexpr (I == 1) return s.s; else if constexpr (I == 2) return s.d; } قبلاً ما باید به صورت زیر مینوشتیم: template <> auto& get<0>(S &s) { return s.n; } template <> auto& get<1>(S &s) { return s.s; } template <> auto& get<2>(S &s) { return s.d; } همانطور که میبینید، مشکل سوال برانگیز اینجاست که کد در این جا ساده تر است. اگر چه در این مورد فقط از یک ساختار ساده استفاده شده است، با برخی از نمونه های واقعی دنیا، کد نهایی باید بسیار پیچیده تر از این باشد بنابراین باید constexpr if کد تمیز تری نسبت به این مورد باشد. این مورد با کامپایلرهای GCC 7.0،MSVC-2017.3 و Clang 3.9 سازگار است. ویژگیهای دیگر ما میتوانیم در رابطه با بسیاری از ویژگی های جدید سیپلاسپلاس صحبت کنیم اما در این پست ما بیشتر در رابطه با قطعات بزرگتر تمرکز کردهایم. با این حال، فقط برای یادآوری، ممکن است بخواهید ویژگیهای زیر را در نظر بگیرید که آنها نیز کد ها را ساده تر میکنند: الگو یا قالبها (templates) عبارت Fold الگو برای کلاس ها بنابراین برای ذکر ویژگیهای بیشتر در رابطه با نسخه جدید در پستهای آن ها را پوشش خواهیم داد. شک نکنید که، سیپلاسپلاس ۱۷ پیشرفت واقعی را در برابر کد های جمع و جور و آسان فراهم گرده است. یکی از بهترین چیزها constexpr است که آن به ما اجازه میدهد کد template/metaprogramming را به روش کد استاندارد شده بنویسیم. این یک مزیت بسیار بزرگی است. ویژگی دوم: پیوند ساخت یافته (که حتی برای حلقه ها کار میکند) مانند حسی را القا میکند که در زبانهای پویایی مثل Python وجود دارد. همانطور که میبینید، تمام ویژگیهای ذکر شده در حال حاضر در Clang، MSVC و GCC قابل اجرا هستند. اگر شما با نسخههای اخیر این کامپایلر ها کار میکنید میتواین بلافاصله با سی++ ۱۷ کار کرده و آن را تجربه کنید.