در برنامهنویسی C++،
عملیات درج درجا (In-Place Construction) به معنای ساختن مستقیم یک عنصر در
محل نهایی آن در حافظه، بدون ایجاد اشیاء موقت و بدون انجام کپی یا
حرکتهای اضافی است. متد emplace که از
C++11 به کانتینرهای استاندارد اضافه شده، این امکان را فراهم میکند تا
با دریافت آرگومانهای سازندهی عنصر، آن را مستقیماً درون کانتینر بسازد . برای std::map، این به معنای ساختن مستقیم یک std::pair<const Key, T> با استفاده از آرگومانهای دادهشده است .
نحوهی عملکرد emplace در مپ
متد emplace در std::map و std::unordered_map، آرگومانهای خود را بهطور کامل به سازندهی عنصر (که همان std::pair<const Key, T> است) ارسال میکند. این تابع تنها در صورتی عنصر جدیدی درج میکند که کلید معادلی در کانتینر وجود نداشته باشد . خروجی آن یک std::pair<iterator, bool> است که bool آن نشاندهندهی موفقیتآمیز بودن درج است . نکتهی بسیار مهم این است که حتی اگر کلید تکراری باشد، عنصر ممکن است ساخته شود و سپس بلافاصله نابود گردد .
مزیت کلیدی: حذف کپی و حرکتهای غیرضروری
مهمترین مزیت emplace نسبت به روشهای قدیمی مانند insert با مقدار از پیش ساختهشده، حذف کپی و حرکتهای اضافی است . بهعنوان مثال، بهجای ساختن یک std::pair بهصورت جداگانه و سپس کپی کردن آن به درون مپ، میتوان مستقیماً آرگومانهای سازندهی کلید و مقدار را به emplace
داد تا در محل ساخته شوند. این موضوع بهویژه برای نوعهایی که کپیبرداری
از آنها پرهزینه است یا اصلاً قابل کپی نیستند، بسیار حیاتی است.
تکنیک piecewise_construct برای ساخت جداگانهی کلید و مقدار
در برخی موارد، کلید و مقدار هر دو نیاز به آرگومانهای متعددی برای سازندهی خود دارند. در چنین شرایطی، استفاده از std::piecewise_construct به همراه std::forward_as_tuple ضروری است . این تکنیک به emplace اجازه میدهد تا کلید و مقدار را بهطور جداگانه و با استفاده از آرگومانهای متفاوت، در محل بسازد. نمونهی کلاسیک آن، ساخت یک std::string با تعداد کاراکتر مشخص بهعنوان مقدار است: m.emplace(std::piecewise_construct, std::forward_as_tuple("c"), std::forward_as_tuple(10, 'c')); که یک کلید با مقدار "c" و یک مقدار با ۱۰ کاراکتر 'c' میسازد .
ملاحظات عملکردی و هشدارها
اگرچه emplace
یک ابزار قدرتمند است، اما دو نکتهی مهم باید مدنظر قرار گیرد. اول
اینکه، در صورت وجود کلید تکراری، ممکن است عنصر ساخته شده و سپس نابود شود
که این خود سربار دارد . دوم اینکه، emplace آرگومانهای خود را به سازندهی std::pair ارسال میکند و این میتواند در برخی موارد منجر به استفاده از سازندهی اشتباه شود. برای رفع این ابهام، از C++17 متد try_emplace
معرفی شده که رفتار بهتری دارد و آرگومانهای کلید و مقدار را بهطور
جداگانه مدیریت میکند و در صورت وجود کلید تکراری، هیچ عنصری نمیسازد .
کلیدواژه ها : std::map emplace-درج درجا در مپ-C++ in-place construction-emplace piecewise construct-std::piecewise_construct-std::forward_as_tuple-مزایای emplace نسبت به insert-ساخت مستقیم در مپ-C++17 map insertion-آموزش emplace-بهینهسازی درج در map-مقایسه emplace و try_emplace-std::pair constructor-map performance optimization