{"id":333123,"date":"2022-05-14T21:00:08","date_gmt":"2022-05-14T21:00:08","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=333123"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=333123","title":{"rendered":"<span>\u041a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f \u0443\u043c\u043d\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f static_ptr&lt;T&gt; \u0432 C++<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ab6\/a7e\/fad\/ab6a7efadf86bdf166a756b9db449614.png\" width=\"780\" height=\"440\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ab6\/a7e\/fad\/ab6a7efadf86bdf166a756b9db449614.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412 C++ \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e &#171;\u0443\u043c\u043d\u044b\u0445 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439&#187; &#8212; <code>std::unique_ptr<\/code>, <code>std::shared_ptr<\/code>, <code>std::weak_ptr<\/code>. \u0422\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0443\u043c\u043d\u044b\u0435 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432 boost<a href=\"https:\/\/www.boost.org\/doc\/libs\/1_79_0\/libs\/smart_ptr\/doc\/html\/smart_ptr.html\" rel=\"noopener noreferrer nofollow\"><sup>1<\/sup><\/a>: <code>intrusive_ptr<\/code>, <code>local_shared_ptr<\/code>.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u0432\u0438\u0434 \u0443\u043c\u043d\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c <code>static_ptr<\/code>. \u0411\u043e\u043b\u044c\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u043e\u043d \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 <code>std::unique_ptr<\/code> \u0431\u0435\u0437 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<h2>std::unique_ptr&lt;T><\/h2>\n<p><code>std::unique_ptr&lt;T><\/code><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/memory\/unique_ptr\" rel=\"noopener noreferrer nofollow\"><sup>2<\/sup><\/a> \u044d\u0442\u043e \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u043c <code>T*<\/code>. \u041d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0432\u0441\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u044b \u043d\u0430 C++ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441.<\/p>\n<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u043f\u0440\u0438\u0447\u0438\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f &#8212; \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u0438\u0437\u043c.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043c\u044b \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u043d\u0435 &#171;\u0437\u043d\u0430\u0435\u043c&#187;, \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u0430\u043a\u043e\u0433\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u043d\u0435\u043a\u043e\u0439 \u0442\u043e\u0447\u043a\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0442\u043e \u0438\u0437-\u0437\u0430 \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u0437\u043d\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0430\u0434\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u0441\u0442\u0435\u043a\u0430, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u0442\u0430\u043a\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u043d\u0430 \u0441\u0442\u0435\u043a\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f &#8212; \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0435\u0433\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043a\u0443\u0447\u0435.<\/p>\n<p>\u041f\u0443\u0441\u0442\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>IEngine<\/code> \u0438 \u0435\u0433\u043e \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0438 <code>TSteamEngine<\/code>, <code>TRocketEngine<\/code>, <code>TEtherEngine<\/code>. \u041e\u0431\u044a\u0435\u043a\u0442 &#171;\u043a\u0430\u043a\u043e\u0433\u043e-\u0442\u043e \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430 <code>IEngine<\/code>, \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0433\u043e \u0432 run-time&#187; \u044d\u0442\u043e \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0438\u043c\u0435\u043d\u043d\u043e <code>std::unique_ptr&lt;IEngine><\/code>, \u0432 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0430\u043c\u044f\u0442\u044c \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0430\u043b\u043b\u043e\u0446\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u043a\u0443\u0447\u0435.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/964\/c4a\/a5d\/964c4aa5d32725dc0e2aca93548b4348.png\" alt=\"std::unique_ptr&lt;IEngine> \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430&#187; title=&#187;std::unique_ptr&lt;IEngine> \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430&#187; width=&#187;262&#8243; height=&#187;302&#8243; data-src=&#187;https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/964\/c4a\/a5d\/964c4aa5d32725dc0e2aca93548b4348.png&#187;\/><figcaption>std::unique_ptr&lt;IEngine> \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430<\/figcaption><\/figure>\n<h2>\u0410\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u044f \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432<\/h2>\n<p>\u0410\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u0432 \u043a\u0443\u0447\u0435 \u043d\u0443\u0436\u043d\u044b \u0434\u043b\u044f &#171;\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432&#187; (<code>std::vector<\/code> \u0441 \u043a\u0443\u0447\u0435\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, etc.), \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0441\u0442\u0435\u043a \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f &#171;\u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432&#187;.<\/p>\n<p>\u0412 Linux \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0441\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c:<\/p>\n<pre><code>ulimit -s<\/code><\/pre>\n<p>\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043d\u0435\u0432\u044b\u0441\u043e\u043a\u043e\u0435 \u0447\u0438\u0441\u043b\u043e, \u043d\u0430 \u043c\u043e\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u044d\u0442\u043e 8192 KiB = 8 MiB. \u0412 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u043f\u0430\u043c\u044f\u0442\u044c \u0438\u0437 \u043a\u0443\u0447\u0438 \u043c\u043e\u0436\u043d\u043e \u0445\u0430\u0432\u0430\u0442\u044c \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442\u0430\u043c\u0438.<\/p>\n<p>\u0410\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u044f \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u043f\u0430\u043c\u044f\u0442\u044c \u0438 \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u043e \u043e\u0442\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043a\u044d\u0448\u0435. \u0414\u043b\u044f \u0443\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u0430\u043a\u0438\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f <strong>memory pool<\/strong> &#8212; \u0435\u0441\u0442\u044c \u043a\u0440\u0443\u0442\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443<a href=\"https:\/\/betterprogramming.pub\/c-memory-pool-and-small-object-allocator-8f27671bd9ee\" rel=\"noopener noreferrer nofollow\"><sup>3<\/sup><\/a>, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0435\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c.<\/p>\n<h2>\u041e\u0431\u044a\u0435\u043a\u0442\u044b \u043d\u0430 \u0441\u0442\u0435\u043a\u0435<\/h2>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 <code>std::unique_ptr<\/code>, \u043d\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u0442\u0435\u043a\u043e\u0432\u044b\u0439?<\/p>\n<p>\u0412 C++ \u0435\u0441\u0442\u044c <code>std::aligned_storage<\/code><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/types\/aligned_storage\" rel=\"noopener noreferrer nofollow\"><sup>4<\/sup><\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0430\u0435\u0442 \u0441\u044b\u0440\u0443\u044e \u043f\u0430\u043c\u044f\u0442\u044c \u043d\u0430 \u0441\u0442\u0435\u043a\u0435, \u0438 \u0432 \u044d\u0442\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 placement new<a href=\"https:\/\/www.geeksforgeeks.org\/placement-new-operator-cpp\/\" rel=\"noopener noreferrer nofollow\"><sup>5<\/sup><\/a> \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 <code>T<\/code>. \u041d\u0430\u0434\u043e \u043f\u0440\u043e\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043f\u0430\u043c\u044f\u0442\u0438 \u0431\u044b\u043b\u043e \u043d\u0435 \u043c\u0435\u043d\u044c\u0448\u0435 \u0447\u0435\u043c <code>sizeof(T)<\/code>.<\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0437\u0430 \u0441\u0447\u0435\u0442 \u043c\u0438\u043a\u0440\u043e\u0441\u043a\u043e\u043f\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043e\u0432\u0435\u0440\u0445\u0435\u0434\u0430 (\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0437\u0430\u043d\u044f\u0442\u044b\u0445 \u0431\u0430\u0439\u0442\u043e\u0432) \u043d\u0430 \u0441\u0442\u0435\u043a\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<h2>sp::static_ptr&lt;T><\/h2>\n<p>\u0418\u043c\u0435\u044f \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u0438\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c stack-only \u0430\u043d\u0430\u043b\u043e\u0433 <code>std::unique_ptr&lt;T><\/code>, \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u0438\u0441\u043a\u0430\u0442\u044c \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0438\u0434\u0435\u044f, \u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u044b, \u043b\u0435\u0436\u0438\u0442 \u043d\u0430 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>\u041f\u0440\u0438\u0434\u0443\u043c\u0430\u0432 \u0442\u0430\u043a\u0438\u0435 \u0441\u043b\u043e\u0432\u0430 \u043a\u0430\u043a <code>stack_ptr<\/code>, <code>static_ptr<\/code> \u0438 \u043f\u0440., \u0438 \u043f\u043e\u0438\u0441\u043a\u0430\u0432 \u0438\u0445 \u043d\u0430 GitHub, \u044f \u043d\u0430\u0448\u0435\u043b \u0432\u043c\u0435\u043d\u044f\u0435\u043c\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 ceph<a href=\"https:\/\/github.com\/ceph\/ceph\" rel=\"noopener noreferrer nofollow\"><sup>6<\/sup><\/a>, \u0432 <code>ceph\/static_ptr.h<\/code><a href=\"https:\/\/github.com\/ceph\/ceph\/blob\/master\/src\/common\/static_ptr.h\" rel=\"noopener noreferrer nofollow\"><sup>7<\/sup><\/a> \u0438 \u0443\u0432\u0438\u0434\u0435\u043b \u0442\u0430\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0438\u0434\u0435\u0438. \u0412\u043f\u0440\u043e\u0447\u0435\u043c, \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043c\u0430\u043b\u043e \u0433\u0434\u0435, \u0438 \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0435\u0441\u0442\u044c \u0440\u044f\u0434 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u043c\u0430\u0445\u043e\u0432.<\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a &#8212; \u0435\u0441\u0442\u044c \u0441\u0430\u043c \u0431\u0443\u0444\u0435\u0440 \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 (\u0432 \u0432\u0438\u0434\u0435 <code>std::aligned_storage<\/code>); \u0438 \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0440\u0443\u043b\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c: \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0434\u0435\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u043e\u0433\u043e \u0442\u0438\u043f\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0435\u0439\u0447\u0430\u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0432 <code>static_ptr<\/code>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/28c\/9af\/42d\/28c9af42d324c26c4e839d1a322bf6ac.png\" alt=\"sp::static_ptr&lt;IEngine> \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430 (\u0431\u0443\u0444\u0435\u0440 \u043d\u0430 32 \u0431\u0430\u0439\u0442\u0430)&#187; title=&#187;sp::static_ptr&lt;IEngine> \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430 (\u0431\u0443\u0444\u0435\u0440 \u043d\u0430 32 \u0431\u0430\u0439\u0442\u0430)&#187; width=&#187;387&#8243; height=&#187;203&#8243; data-src=&#187;https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/28c\/9af\/42d\/28c9af42d324c26c4e839d1a322bf6ac.png&#187;\/><figcaption>sp::static_ptr&lt;IEngine> \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430 (\u0431\u0443\u0444\u0435\u0440 \u043d\u0430 32 \u0431\u0430\u0439\u0442\u0430)<\/figcaption><\/figure>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f: \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043b\u043e\u0436\u0435\u043d move?<\/h2>\n<p>\u0417\u0434\u0435\u0441\u044c \u044f \u043e\u043f\u0438\u0448\u0443 \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0445 \u043a\u0430\u043c\u043d\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0432\u0441\u043f\u043b\u044b\u0442\u044c.<\/p>\n<p>\u0421\u0430\u043c \u043a\u043b\u0430\u0441\u0441 <code>static_ptr<\/code> \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 namespace <code>sp<\/code> (\u043e\u0442 <strong>s<\/strong>tatic <strong>p<\/strong>ointer).<\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432, \u0443\u043c\u043d\u044b\u0445 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439, \u0438 \u043f\u0440\u043e\u0447\u0438\u0445 \u0432\u0435\u0449\u0435\u0439 &#8212; \u044d\u0442\u043e \u0432\u043e\u043e\u0431\u0449\u0435 \u043e\u0434\u043d\u0438 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c \u043d\u0430 C++, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0437\u0430\u0434\u0443\u043c\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u0434 \u0432\u0435\u0449\u0430\u043c\u0438, \u043f\u0440\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u043d\u0435 \u043f\u043e\u0434\u043e\u0437\u0440\u0435\u0432\u0430\u044e\u0442.<\/p>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0432\u044b\u0437\u0432\u0430\u0442\u044c move-\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0443\u0447\u0430\u0441\u0442\u043a\u0430 \u043f\u0430\u043c\u044f\u0442\u0438 \u0432 \u0434\u0440\u0443\u0433\u043e\u0439. \u041c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cpp\">template &lt;typename T> struct move_constructer {     static void call(T* lhs, T* rhs) {         new (lhs) T(std::move(*rhs));     } }; \/\/ call `move_constructer&lt;T>::call(dst, src);`<\/code><\/pre>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u043a\u043b\u0430\u0441\u0441 <code>T<\/code> \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 move-\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430?<\/p>\n<p>\u0415\u0441\u0442\u044c \u0448\u0430\u043d\u0441, \u0447\u0442\u043e <code>T<\/code> \u0438\u043c\u0435\u0435\u0442 move-\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u044f, \u0442\u043e\u0433\u0434\u0430 \u043d\u0430\u0434\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e. \u0415\u0441\u043b\u0438 \u0438 \u0435\u0433\u043e \u043d\u0435\u0442, \u0442\u043e \u043d\u0430\u0434\u043e &#171;\u0441\u043b\u043e\u043c\u0430\u0442\u044c&#187; \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044e.<\/p>\n<p>\u0427\u0435\u043c \u043d\u043e\u0432\u0435\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 C++, \u0442\u0435\u043c \u043b\u0435\u0433\u0447\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434 \u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0432\u0435\u0449\u0435\u0439. \u041f\u043e\u043b\u0443\u0447\u0438\u043c \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434 (\u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 C++<strong>17<\/strong>):<\/p>\n<pre><code class=\"cpp\">template &lt;typename T> struct move_constructer {     static void call(T* lhs, T* rhs) {         if constexpr (std::is_move_constructible_v&lt;T>) {             new (lhs) T(std::move(*rhs));         } else if constexpr (std::is_default_constructible_v&lt;T> &amp;&amp; std::is_move_assignable_v&lt;T>) {             new (lhs) T();             *lhs = std::move(*rhs);         } else {             []&lt;bool flag = false>(){ static_assert(flag, \"move constructor disabled\"); }();         }     } };<\/code><\/pre>\n<p>(\u043d\u0430 10 \u0441\u0442\u0440\u043e\u043a\u0435 \u0441\u043b\u043e\u043c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0432 \u0432\u0438\u0434\u0435 <code>static_assert<\/code> \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441 \u0445\u0430\u043a\u043e\u043c<a href=\"https:\/\/stackoverflow.com\/a\/64354296\" rel=\"noopener noreferrer nofollow\"><sup>8<\/sup><\/a>)<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u043d\u0435\u043f\u043b\u043e\u0445\u043e \u0431\u044b \u0435\u0449\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c <code>noexcept<\/code>-\u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u043a\u043e\u0433\u0434\u0430 \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u0412 C++<strong>20<\/strong> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434, \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442:<\/p>\n<pre><code class=\"cpp\">template &lt;typename T> struct move_constructer {     static void call(T* lhs, T* rhs)         noexcept (std::is_nothrow_move_constructible_v&lt;T>)         requires (std::is_move_constructible_v&lt;T>)     {         new (lhs) T(std::move(*rhs));     }      static void call(T* lhs, T* rhs)         noexcept (std::is_nothrow_default_constructible_v&lt;T> &amp;&amp; std::is_nothrow_move_assignable_v&lt;T>)         requires (!std::is_move_constructible_v&lt;T> &amp;&amp; std::is_default_constructible_v&lt;T> &amp;&amp; std::is_move_assignable_v&lt;T>)     {         new (lhs) T();         *lhs = std::move(*rhs);     } };<\/code><\/pre>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0441 \u0440\u0430\u0437\u0431\u043e\u0440\u043e\u043c \u043a\u0435\u0439\u0441\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 <code>move_assigner<\/code>. \u041c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0435\u0449\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c <code>copy_constructer<\/code> \u0438 <code>copy_assigner<\/code>, \u043d\u043e \u0432 \u043d\u0430\u0448\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u043d\u0438 \u043d\u0435 \u043d\u0443\u0436\u043d\u044b. \u0412 <code>static_ptr<\/code> \u0431\u0443\u0434\u0443\u0442 \u0443\u0434\u0430\u043b\u0435\u043d\u044b copy constructor \u0438 copy assignment operator (\u043a\u0430\u043a \u0438 \u0432 <code>unique_ptr<\/code>).<\/p>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f: std::type_info \u043d\u0430 \u043a\u043e\u043b\u0435\u043d\u043a\u0435<\/h2>\n<p>\u0425\u043e\u0442\u044f \u0432 <code>static_ptr<\/code> \u043c\u043e\u0436\u0435\u0442 \u043b\u0435\u0436\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043d\u0430\u043c \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e &#171;\u0437\u043d\u0430\u0442\u044c&#187; \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0437\u0430 \u0442\u0438\u043f \u0442\u0430\u043c \u043b\u0435\u0436\u0438\u0442. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0434\u0435\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u043e\u0447\u0438\u0435 \u0432\u0435\u0449\u0438.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u043f\u044b\u0442\u043e\u043a \u044f \u0432\u044b\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0442\u0430\u043a\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 &#8212; \u043d\u0443\u0436\u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 <code>ops<\/code>:<\/p>\n<pre><code class=\"cpp\">struct ops {     using binary_func = void(*)(void* dst, void* src);     using unary_func = void(*)(void* dst);      binary_func move_construct_func;     binary_func move_assign_func;     unary_func destruct_func; };<\/code><\/pre>\n<p>\u0418 \u043f\u0430\u0440\u0430 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 <code>void*<\/code> \u0432 <code>T*<\/code>&#8230;<\/p>\n<pre><code class=\"cpp\">template&lt;typename T, typename Functor> void call_typed_func(void* dst, void* src) {     Functor::call(static_cast&lt;T*>(dst), static_cast&lt;T*>(src)); }  template&lt;typename T> void destruct_func(void* dst) {     static_cast&lt;T*>(dst)->~T(); }<\/code><\/pre>\n<p>\u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0438\u043f\u0430 <code>T<\/code> \u0438\u043c\u0435\u0442\u044c \u0441\u0432\u043e\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 <code>ops<\/code>:<\/p>\n<pre><code class=\"cpp\">template&lt;typename T> static constexpr ops ops_for{     .move_construct_func = &amp;call_typed_func&lt;T, move_constructer&lt;T>>,     .move_assign_func = &amp;call_typed_func&lt;T, move_assigner&lt;T>>,     .destruct_func = &amp;destruct_func&lt;T>, }; using ops_ptr = const ops*;<\/code><\/pre>\n<p><code>static_ptr<\/code> \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 <code>ops_for&lt;T><\/code>, \u0433\u0434\u0435 <code>T<\/code> \u044d\u0442\u043e \u043a\u043b\u0430\u0441\u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0435\u0439\u0447\u0430\u0441 \u043b\u0435\u0436\u0438\u0442 \u0432 <code>static_ptr<\/code>.<\/p>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f: I like to move it, move it<\/h2>\n<p>\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c <code>static_ptr<\/code> \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u043b\u044c\u0437\u044f &#8212; \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u0443\u0432\u0430\u0442\u044c \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 <code>static_ptr<\/code>. \u0412\u044b\u0431\u043e\u0440 \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u043c\u0443\u0432\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0437\u0430 \u0442\u0438\u043f \u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043b\u0435\u0436\u0430\u0442 \u0432 \u044d\u0442\u0438\u0445 \u0434\u0432\u0443\u0445 <code>static_ptr<\/code>:<\/p>\n<ol>\n<li>\n<p>\u041e\u0431\u0430 <code>static_ptr<\/code> \u043f\u0443\u0441\u0442\u044b\u0435 (<code>dst_ops = src_ops = nullptr<\/code>): \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p><code>static_ptr<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0442\u0438\u043f (<code>dst_ops = src_ops<\/code>): \u0434\u0435\u043b\u0430\u0435\u043c <strong>move assign<\/strong> \u0438 \u0440\u0430\u0437\u0440\u0443\u0448\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 <code>src<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>static_ptr<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0442\u0438\u043f\u044b (<code>dst_ops != src_ops<\/code>): \u0440\u0430\u0437\u0440\u0443\u0448\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 <code>dst<\/code>, \u0434\u0435\u043b\u0430\u0435\u043c <strong>move construct<\/strong>, \u0440\u0430\u0437\u0440\u0443\u0448\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 <code>src<\/code>, \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u0435 <code>dst_ops = src_ops<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0442\u0430\u043a\u043e\u0439 \u043c\u0435\u0442\u043e\u0434:<\/p>\n<pre><code class=\"cpp\">\/\/ moving objects using ops static void move_construct(void* dst_buf, ops_ptr&amp; dst_ops,                            void* src_buf, ops_ptr&amp; src_ops) {     if (!src_ops &amp;&amp; !dst_ops) {         \/\/ both object are nullptr_t, do nothing         return;     } else if (src_ops == dst_ops) {         \/\/ objects have the same type, make move         (*src_ops->move_assign_func)(dst_buf, src_buf);         (*src_ops->destruct_func)(src_buf);         src_ops = nullptr;     } else {         \/\/ objects have different type         \/\/ delete the old object         if (dst_ops) {             (*dst_ops->destruct_func)(dst_buf);             dst_ops = nullptr;         }         \/\/ construct the new object         if (src_ops) {             (*src_ops->move_construct_func)(dst_buf, src_buf);             (*src_ops->destruct_func)(src_buf);         }         dst_ops = src_ops;         src_ops = nullptr;     } }<\/code><\/pre>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f: \u0440\u0430\u0437\u043c\u0435\u0440 \u0431\u0443\u0444\u0435\u0440\u0430 \u0438 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435<\/h2>\n<p>\u0421\u0435\u0439\u0447\u0430\u0441 \u043d\u0430\u0434\u043e \u0440\u0435\u0448\u0438\u0442\u044c, \u043a\u0430\u043a\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0431\u0443\u0444\u0435\u0440\u0430 \u0438 \u043a\u0430\u043a\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435<a href=\"https:\/\/en.cppreference.com\/w\/c\/language\/object\" rel=\"noopener noreferrer nofollow\"><sup>9<\/sup><\/a>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e <code>std::aligned_storage<\/code> \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0437\u043d\u0430\u0442\u044c \u044d\u0442\u0438 \u0434\u0432\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430-\u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0442\u044c \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430-\u043f\u0440\u0435\u0434\u043a\u0430<a href=\"https:\/\/godbolt.org\/z\/cbjoo3v59\" rel=\"noopener noreferrer nofollow\"><sup>10<\/sup><\/a>. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u044b\u0432\u0430\u0435\u0442. \u0412 \u044d\u0442\u043e\u043c \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0442\u0438\u043f <code>std::max_align_t<\/code><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/types\/max_align_t\" rel=\"noopener noreferrer nofollow\"><sup>11<\/sup><\/a>:<\/p>\n<pre><code class=\"cpp\">static constexpr std::size_t align = alignof(std::max_align_t);<\/code><\/pre>\n<p>\u041d\u0430 \u043c\u043e\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 16, \u043d\u043e \u0433\u0434\u0435-\u0442\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041a\u0441\u0442\u0430\u0442\u0438, \u043f\u0430\u043c\u044f\u0442\u044c \u0438\u0437 \u043a\u0443\u0447\u0438 (\u0438\u0437 <code>malloc<\/code>) \u0442\u043e\u0436\u0435 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u043c\u0443 alignment, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.<\/p>\n<p>\u0414\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0431\u0443\u0444\u0435\u0440\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 16 \u0431\u0430\u0439\u0442 \u0438\u043b\u0438 \u0432 <code>sizeof(T)<\/code> &#8212; \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435.<\/p>\n<pre><code class=\"cpp\">template&lt;typename T> struct static_ptr_traits {     static constexpr std::size_t buffer_size = std::max(static_cast&lt;std::size_t>(16), sizeof(T)); };<\/code><\/pre>\n<p>\u041f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043d\u0430 \u0441\u0432\u043e\u044e \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043c\u0435\u0449\u0430\u043b\u0438\u0441\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0432\u0441\u0435\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432-\u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u043e\u0432. \u0416\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0432 \u0432\u0438\u0434\u0435 \u043c\u0430\u043a\u0440\u043e\u0441\u0430, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0438\u0441\u0430\u0442\u044c. \u041c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u043c\u0430\u043a\u0440\u043e\u0441 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0431\u0443\u0444\u0435\u0440\u0430 \u0432 \u043e\u0434\u043d\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435:<\/p>\n<pre><code class=\"cpp\">#define STATIC_PTR_BUFFER_SIZE(Tp, size)                   \\ namespace sp {                                             \\     template&lt;> struct static_ptr_traits&lt;Tp> {              \\         static constexpr std::size_t buffer_size = size;   \\     };                                                     \\ }  \/\/ example: STATIC_PTR_BUFFER_SIZE(IEngine, 1024)<\/code><\/pre>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 &#171;\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043b\u0441\u044f&#187; \u0432\u0441\u0435\u043c\u0438 \u043a\u043b\u0430\u0441\u0441\u0430\u043c\u0438-\u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430\u043c\u0438 \u043d\u0443\u0436\u043d\u043e\u0433\u043e. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u043c\u0430\u043a\u0440\u043e\u0441 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <code>std::is_base<\/code>:<\/p>\n<pre><code class=\"cpp\">#define STATIC_PTR_INHERITED_BUFFER_SIZE(Tp, size)         \\ namespace sp {                                             \\     template&lt;typename T> requires std::is_base_of_v&lt;Tp, T> \\     struct static_ptr_traits&lt;T> {                          \\         static constexpr std::size_t buffer_size = size;   \\     };                                                     \\ }  \/\/ example: STATIC_PTR_INHERITED_BUFFER_SIZE(IEngine, 1024)<\/code><\/pre>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f: sp::static_ptr&lt;T><\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u0430\u043c\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430. \u0423 \u043d\u0435\u0433\u043e \u0432\u0441\u0435\u0433\u043e \u0434\u0432\u0430 \u043f\u043e\u043b\u044f &#8212; \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 <code>ops<\/code> \u0438 \u0431\u0443\u0444\u0435\u0440 \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430:<\/p>\n<pre><code class=\"cpp\">template&lt;typename Base> requires(!std::is_void_v&lt;Base>) class static_ptr { private:     static constexpr std::size_t buffer_size = static_ptr_traits&lt;Base>::buffer_size;     static constexpr std::size_t align = alignof(std::max_align_t);      \/\/ Struct for calling object's operators     \/\/ equals to `nullptr` when `buf_` contains no object     \/\/ equals to `ops_for&lt;T>` when `buf_` contains a `T` object     ops_ptr ops_;      \/\/ Storage for underlying `T` object     \/\/ this is mutable so that `operator*` and `get()` can     \/\/ be marked const     mutable std::aligned_storage_t&lt;buffer_size, align> buf_;      \/\/ ...<\/code><\/pre>\n<p>\u0412 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <code>reset<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 &#8212; \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0447\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f:<\/p>\n<pre><code class=\"cpp\">    \/\/ destruct the underlying object     void reset() noexcept(std::is_nothrow_destructible_v&lt;Base>) {         if (ops_) {             (ops_->destruct_func)(&amp;buf_);             ops_ = nullptr;         }     }<\/code><\/pre>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u044b \u043f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0441 <code>std::unique_ptr<\/code>:<\/p>\n<pre><code class=\"cpp\">    \/\/ operators, ctors, dtor     static_ptr() noexcept : ops_{nullptr} {}      static_ptr(std::nullptr_t) noexcept : ops_{nullptr} {}     static_ptr&amp; operator=(std::nullptr_t) noexcept(std::is_nothrow_destructible_v&lt;Base>) {         reset();         return *this;     }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c move constructor \u0438 move assignment operator. \u0427\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u043b\u0441\u044f \u0442\u043e\u0442 \u0436\u0435 \u0442\u0438\u043f, \u043d\u0430\u0434\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cpp\">    static_ptr(static_ptr&amp;&amp; rhs) : ops_{nullptr} {         move_construct(&amp;buf_, ops_, &amp;rhs.buf_, rhs.ops_);     }      static_ptr&amp; operator=(static_ptr&amp;&amp; rhs) {         move_construct(&amp;buf_, ops_, &amp;rhs.buf_, rhs.ops_);         return *this;     }<\/code><\/pre>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u043b\u0443\u0447\u0448\u0435, \u0435\u0441\u043b\u0438 \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c <code>static_ptr<\/code> \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0442\u0438\u043f\u043e\u0432. \u0414\u0440\u0443\u0433\u043e\u0439 \u0442\u0438\u043f \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u043b\u0435\u0437\u0430\u0442\u044c \u0432 \u0431\u0443\u0444\u0435\u0440 \u0438 \u0431\u044b\u0442\u044c \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u043e\u043c \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0442\u0438\u043f\u0430:<\/p>\n<pre><code class=\"cpp\">    template&lt;typename Derived>     struct derived_class_check {         static constexpr bool ok = sizeof(Derived) &lt;= buffer_size &amp;&amp; std::is_base_of_v&lt;Base, Derived>;     };<\/code><\/pre>\n<p>\u0418 \u043d\u0430\u0434\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c &#171;\u0434\u0440\u0443\u0437\u044c\u044f\u043c\u0438&#187; \u0432\u0441\u0435 \u0438\u043d\u0441\u0442\u0430\u043d\u0446\u0438\u0430\u0446\u0438\u0438 \u043a\u043b\u0430\u0441\u0441\u0430:<\/p>\n<pre><code class=\"cpp\">    \/\/ support static_ptr's conversions of different types     template &lt;typename T> friend class static_ptr;<\/code><\/pre>\n<p>\u0422\u043e\u0433\u0434\u0430 \u0434\u0432\u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cpp\">    template&lt;typename Derived = Base>     static_ptr(static_ptr&lt;Derived>&amp;&amp; rhs)         requires(derived_class_check&lt;Derived>::ok)         : ops_{nullptr}     {         move_construct(&amp;buf_, ops_, &amp;rhs.buf_, rhs.ops_);     }      template&lt;typename Derived = Base>     static_ptr&amp; operator=(static_ptr&lt;Derived>&amp;&amp; rhs)         requires(derived_class_check&lt;Derived>::ok)     {         move_construct(&amp;buf_, ops_, &amp;rhs.buf_, rhs.ops_);         return *this;     }<\/code><\/pre>\n<p>\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u043e:<\/p>\n<pre><code class=\"cpp\">    static_ptr(const static_ptr&amp;) = delete;     static_ptr&amp; operator=(const static_ptr&amp;) = delete;<\/code><\/pre>\n<p>\u0414\u0435\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0440\u0430\u0437\u0440\u0443\u0448\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 \u0431\u0443\u0444\u0435\u0440\u0435:<\/p>\n<pre><code class=\"cpp\">    ~static_ptr() {         reset();     }<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 \u0431\u0443\u0444\u0435\u0440\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <code>emplace<\/code>. \u0421\u0442\u0430\u0440\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0443\u0434\u0430\u043b\u0438\u0442\u0441\u044f (\u0435\u0441\u043b\u0438 \u043e\u043d \u0435\u0441\u0442\u044c), \u0432 \u0431\u0443\u0444\u0435\u0440\u0435 \u0441\u043e\u0437\u0434\u0430\u0441\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0439, \u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 <code>ops<\/code>.<\/p>\n<pre><code class=\"cpp\">    \/\/ in-place (re)initialization     template&lt;typename Derived = Base, typename ...Args>     Derived&amp; emplace(Args&amp;&amp;... args)         noexcept(std::is_nothrow_constructible_v&lt;Derived, Args...>)         requires(derived_class_check&lt;Derived>::ok)     {         reset();         Derived* derived = new (&amp;buf_) Derived(std::forward&lt;Args>(args)...);         ops_ = &amp;ops_for&lt;Derived>;         return *derived;     }<\/code><\/pre>\n<p>\u041c\u0435\u0442\u043e\u0434\u044b-\u0430\u043a\u0441\u0435\u0441\u043e\u0440\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0430\u043a\u0438\u0435 \u0436\u0435, \u043a\u0430\u043a \u0443 <code>std::unique_ptr<\/code>:<\/p>\n<pre><code class=\"cpp\">    \/\/ accessors     Base* get() noexcept {         return ops_ ? reinterpret_cast&lt;Base*>(&amp;buf_) : nullptr;     }     const Base* get() const noexcept {         return ops_ ? reinterpret_cast&lt;const Base*>(&amp;buf_) : nullptr;     }      Base&amp; operator*() noexcept { return *get(); }     const Base&amp; operator*() const noexcept { return *get(); }      Base* operator&amp;() noexcept { return get(); }     const Base* operator&amp;() const noexcept { return get(); }      Base* operator->() noexcept { return get(); }     const Base* operator->() const noexcept { return get(); }      operator bool() const noexcept { return ops_; }<\/code><\/pre>\n<p>\u041f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0441 <code>std::make_unique<\/code> \u0438 <code>std::make_shared<\/code>, \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <code>sp::make_static<\/code>:<\/p>\n<pre><code class=\"cpp\">template&lt;typename T, class ...Args> static static_ptr&lt;T> make_static(Args&amp;&amp;... args) {     static_ptr&lt;T> ptr;     ptr.emplace(std::forward&lt;Args>(args)...);     return ptr; }<\/code><\/pre>\n<p><strong>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043d\u0430 GitHub<\/strong><a href=\"https:\/\/github.com\/Izaron\/static_ptr\" rel=\"noopener noreferrer nofollow\"><strong><sup>12<\/sup><\/strong><\/a><strong>!<\/strong><\/p>\n<h2>\u041a\u0430\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f sp::static_ptr&lt;T>?<\/h2>\n<p>\u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e! \u042f \u0441\u0434\u0435\u043b\u0430\u043b \u044e\u043d\u0438\u0442-\u0442\u0435\u0441\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043b\u0430\u0439\u0444\u0442\u0430\u0439\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u0436\u0438\u0432\u0443\u0449\u0438\u0445 \u0432\u043d\u0443\u0442\u0440\u0438 <code>static_ptr<\/code><a href=\"https:\/\/github.com\/Izaron\/static_ptr\/blob\/main\/test\/test_derived.cc\" rel=\"noopener noreferrer nofollow\"><sup>13<\/sup><\/a>.<\/p>\n<p>\u0412 \u0442\u0435\u0441\u0442\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e <code>static_ptr<\/code> \u0438 \u0442\u043e, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0438\u0445.<\/p>\n<h2>\u0411\u0435\u043d\u0447\u043c\u0430\u0440\u043a<\/h2>\n<p>\u0414\u043b\u044f \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u043e\u0432 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 <code>google\/benchmark<\/code><a href=\"https:\/\/github.com\/google\/benchmark\" rel=\"noopener noreferrer nofollow\"><sup>14<\/sup><\/a>. \u041a\u043e\u0434 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0435\u0441\u0442\u044c \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<a href=\"https:\/\/github.com\/Izaron\/static_ptr\/blob\/main\/benchmark\/benchmark.cc\" rel=\"noopener noreferrer nofollow\"><sup>15<\/sup><\/a>.<\/p>\n<p>\u042f \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b \u0434\u0432\u0430 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f, \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0438\u0437 \u043d\u0438\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f <code>std::unique_ptr<\/code> \u0438 <code>sp::static_ptr<\/code>:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0443\u043c\u043d\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f \u0438 \u0432\u044b\u0437\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0418\u0442\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e \u0432\u0435\u043a\u0442\u043e\u0440\u0443 \u0438\u0437 128 \u0443\u043c\u043d\u044b\u0445 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439, \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434.<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u043c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0432\u044b\u0438\u0433\u0440\u044b\u0448 \u0443 <code>sp::static_ptr<\/code> \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0437\u0430 \u0441\u0447\u0435\u0442 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438, \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0437\u0430 \u0441\u0447\u0435\u0442 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043f\u0430\u043c\u044f\u0442\u0438. \u0425\u043e\u0442\u044f, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u044b \u043e\u0447\u0435\u043d\u044c \u0443\u043c\u043d\u044b\u0435 \u0438 \u0443\u043c\u0435\u044e\u0442 \u0445\u043e\u0440\u043e\u0448\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c &#171;\u043f\u043b\u043e\u0445\u0438\u0435&#187; \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0444\u043b\u0430\u0433\u043e\u0432 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a \u0432 \u0441\u0431\u043e\u0440\u043a\u0435 Debug:<\/p>\n<pre><code>***WARNING*** Library was built as DEBUG. Timings may be affected. ------------------------------------------------------------------------------------------------- Benchmark                                                       Time             CPU   Iterations ------------------------------------------------------------------------------------------------- BM_SingleSmartPointer&lt;std::unique_ptr&lt;IEngine>>               207 ns          207 ns      3244590 BM_SingleSmartPointer&lt;sp::static_ptr&lt;IEngine>>               39.1 ns         39.1 ns     17474886 BM_IteratingOverSmartPointer&lt;std::unique_ptr&lt;IEngine>>       3368 ns         3367 ns       204196 BM_IteratingOverSmartPointer&lt;sp::static_ptr&lt;IEngine>>        1716 ns         1716 ns       397344<\/code><\/pre>\n<p>\u0412 \u0441\u0431\u043e\u0440\u043a\u0435 Release:<\/p>\n<pre><code>------------------------------------------------------------------------------------------------- Benchmark                                                       Time             CPU   Iterations ------------------------------------------------------------------------------------------------- BM_SingleSmartPointer&lt;std::unique_ptr&lt;IEngine>>              14.5 ns         14.5 ns     47421573 BM_SingleSmartPointer&lt;sp::static_ptr&lt;IEngine>>               3.57 ns         3.57 ns    197401957 BM_IteratingOverSmartPointer&lt;std::unique_ptr&lt;IEngine>>        198 ns          198 ns      3573888 BM_IteratingOverSmartPointer&lt;sp::static_ptr&lt;IEngine>>         195 ns          195 ns      3627462<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0435\u0441\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0432\u044b\u0438\u0433\u0440\u044b\u0448 \u0432 \u043f\u0435\u0440\u0444\u043e\u043c\u0430\u043d\u0441\u0435 \u0443 <code>sp::static_ptr<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 stack-only \u0430\u043d\u0430\u043b\u043e\u0433 <code>std::unique_ptr<\/code>.<\/p>\n<h2>\u0421\u0441\u044b\u043b\u043a\u0438<\/h2>\n<ol>\n<li>\n<p><a href=\"https:\/\/www.boost.org\/doc\/libs\/1_79_0\/libs\/smart_ptr\/doc\/html\/smart_ptr.html\" rel=\"noopener noreferrer nofollow\">Boost.SmartPtr<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/memory\/unique_ptr\" rel=\"noopener noreferrer nofollow\">std::unique_ptr &#8212; cppreference.com<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/betterprogramming.pub\/c-memory-pool-and-small-object-allocator-8f27671bd9ee\" rel=\"noopener noreferrer nofollow\">C++ Memory Pool and Small Object Allocator | by Debby Nirwan<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/types\/aligned_storage\" rel=\"noopener noreferrer nofollow\">std::aligned_storage &#8212; cppreference.com<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.geeksforgeeks.org\/placement-new-operator-cpp\/\" rel=\"noopener noreferrer nofollow\">Placement new operator in C++ &#8212; GeeksforGeeks<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/ceph\/ceph\" rel=\"noopener noreferrer nofollow\">ceph &#8212; github.com<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/ceph\/ceph\/blob\/master\/src\/common\/static_ptr.h\" rel=\"noopener noreferrer nofollow\">ceph\/static_ptr.h &#8212; github.com<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/stackoverflow.com\/a\/64354296\" rel=\"noopener noreferrer nofollow\">c++ &#8212; constexpr if and static_assert<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/en.cppreference.com\/w\/c\/language\/object\" rel=\"noopener noreferrer nofollow\">Objects and alignment &#8212; cppreference.com<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/godbolt.org\/z\/cbjoo3v59\" rel=\"noopener noreferrer nofollow\">godbolt.com<\/a> &#8212; \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430-\u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430 \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u0443 \u043a\u043b\u0430\u0441\u0441\u0430-\u043f\u0440\u0435\u0434\u043a\u0430<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/types\/max_align_t\" rel=\"noopener noreferrer nofollow\">std::max_align_t &#8212; cppreference.com<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/Izaron\/static_ptr\" rel=\"noopener noreferrer nofollow\">Izaron\/static_ptr &#8212; github.com<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/Izaron\/static_ptr\/blob\/main\/test\/test_derived.cc\" rel=\"noopener noreferrer nofollow\">Izaron\/static_ptr, \u0442\u0435\u0441\u0442 test_derives.cc &#8212; github.com<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/google\/benchmark\" rel=\"noopener noreferrer nofollow\">google\/benchmark &#8212; github.com<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/Izaron\/static_ptr\/blob\/main\/benchmark\/benchmark.cc\" rel=\"noopener noreferrer nofollow\">Izaron\/static_ptr, \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a benchmark.cc &#8212; github.com<\/a><\/p>\n<\/li>\n<\/ol>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/665632\/\"> https:\/\/habr.com\/ru\/post\/665632\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412 C++ \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e &#171;\u0443\u043c\u043d\u044b\u0445 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439&#187; &#8212; <code>std::unique_ptr<\/code>, <code>std::shared_ptr<\/code>, <code>std::weak_ptr<\/code>. \u0422\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0443\u043c\u043d\u044b\u0435 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432 boost<a href=\"https:\/\/www.boost.org\/doc\/libs\/1_79_0\/libs\/smart_ptr\/doc\/html\/smart_ptr.html\" rel=\"noopener noreferrer nofollow\"><sup>1<\/sup><\/a>: <code>intrusive_ptr<\/code>, <code>local_shared_ptr<\/code>.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u0432\u0438\u0434 \u0443\u043c\u043d\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c <code>static_ptr<\/code>. \u0411\u043e\u043b\u044c\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u043e\u043d \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 <code>std::unique_ptr<\/code> \u0431\u0435\u0437 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<h2>std::unique_ptr&lt;T><\/h2>\n<p><code>std::unique_ptr&lt;T><\/code><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/memory\/unique_ptr\" rel=\"noopener noreferrer nofollow\"><sup>2<\/sup><\/a> \u044d\u0442\u043e \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u043c <code>T*<\/code>. \u041d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0432\u0441\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u044b \u043d\u0430 C++ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441.<\/p>\n<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u043f\u0440\u0438\u0447\u0438\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f &#8212; \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u0438\u0437\u043c.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043c\u044b \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u043d\u0435 &#171;\u0437\u043d\u0430\u0435\u043c&#187;, \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u0430\u043a\u043e\u0433\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u043d\u0435\u043a\u043e\u0439 \u0442\u043e\u0447\u043a\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0442\u043e \u0438\u0437-\u0437\u0430 \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u0437\u043d\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0430\u0434\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u0441\u0442\u0435\u043a\u0430, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u0442\u0430\u043a\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u043d\u0430 \u0441\u0442\u0435\u043a\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f &#8212; \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0435\u0433\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043a\u0443\u0447\u0435.<\/p>\n<p>\u041f\u0443\u0441\u0442\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>IEngine<\/code> \u0438 \u0435\u0433\u043e \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0438 <code>TSteamEngine<\/code>, <code>TRocketEngine<\/code>, <code>TEtherEngine<\/code>. \u041e\u0431\u044a\u0435\u043a\u0442 &#171;\u043a\u0430\u043a\u043e\u0433\u043e-\u0442\u043e \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430 <code>IEngine<\/code>, \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0433\u043e \u0432 run-time&#187; \u044d\u0442\u043e \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0438\u043c\u0435\u043d\u043d\u043e <code>std::unique_ptr&lt;IEngine><\/code>, \u0432 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0430\u043c\u044f\u0442\u044c \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0430\u043b\u043b\u043e\u0446\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u043a\u0443\u0447\u0435.<\/p>\n<figure class=\"\"> \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430&#187; title=&#187;std::unique_ptr&lt;IEngine> \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430&#187; width=&#187;262&#8243; height=&#187;302&#8243; data-src=&#187;https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/964\/c4a\/a5d\/964c4aa5d32725dc0e2aca93548b4348.png&#187;\/><figcaption>std::unique_ptr&lt;IEngine> \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430<\/figcaption><\/figure>\n<h2>\u0410\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u044f \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432<\/h2>\n<p>\u0410\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u0432 \u043a\u0443\u0447\u0435 \u043d\u0443\u0436\u043d\u044b \u0434\u043b\u044f &#171;\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432&#187; (<code>std::vector<\/code> \u0441 \u043a\u0443\u0447\u0435\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, etc.), \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0441\u0442\u0435\u043a \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f &#171;\u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432&#187;.<\/p>\n<p>\u0412 Linux \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0441\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c:<\/p>\n<pre><code>ulimit -s<\/code><\/pre>\n<p>\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043d\u0435\u0432\u044b\u0441\u043e\u043a\u043e\u0435 \u0447\u0438\u0441\u043b\u043e, \u043d\u0430 \u043c\u043e\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u044d\u0442\u043e 8192 KiB = 8 MiB. \u0412 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u043f\u0430\u043c\u044f\u0442\u044c \u0438\u0437 \u043a\u0443\u0447\u0438 \u043c\u043e\u0436\u043d\u043e \u0445\u0430\u0432\u0430\u0442\u044c \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442\u0430\u043c\u0438.<\/p>\n<p>\u0410\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u044f \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u043f\u0430\u043c\u044f\u0442\u044c \u0438 \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u043e \u043e\u0442\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043a\u044d\u0448\u0435. \u0414\u043b\u044f \u0443\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u0430\u043a\u0438\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f <strong>memory pool<\/strong> &#8212; \u0435\u0441\u0442\u044c \u043a\u0440\u0443\u0442\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443<a href=\"https:\/\/betterprogramming.pub\/c-memory-pool-and-small-object-allocator-8f27671bd9ee\" rel=\"noopener noreferrer nofollow\"><sup>3<\/sup><\/a>, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0435\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c.<\/p>\n<h2>\u041e\u0431\u044a\u0435\u043a\u0442\u044b \u043d\u0430 \u0441\u0442\u0435\u043a\u0435<\/h2>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 <code>std::unique_ptr<\/code>, \u043d\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u0442\u0435\u043a\u043e\u0432\u044b\u0439?<\/p>\n<p>\u0412 C++ \u0435\u0441\u0442\u044c <code>std::aligned_storage<\/code><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/types\/aligned_storage\" rel=\"noopener noreferrer nofollow\"><sup>4<\/sup><\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0430\u0435\u0442 \u0441\u044b\u0440\u0443\u044e \u043f\u0430\u043c\u044f\u0442\u044c \u043d\u0430 \u0441\u0442\u0435\u043a\u0435, \u0438 \u0432 \u044d\u0442\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 placement new<a href=\"https:\/\/www.geeksforgeeks.org\/placement-new-operator-cpp\/\" rel=\"noopener noreferrer nofollow\"><sup>5<\/sup><\/a> \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 <code>T<\/code>. \u041d\u0430\u0434\u043e \u043f\u0440\u043e\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043f\u0430\u043c\u044f\u0442\u0438 \u0431\u044b\u043b\u043e \u043d\u0435 \u043c\u0435\u043d\u044c\u0448\u0435 \u0447\u0435\u043c <code>sizeof(T)<\/code>.<\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0437\u0430 \u0441\u0447\u0435\u0442 \u043c\u0438\u043a\u0440\u043e\u0441\u043a\u043e\u043f\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043e\u0432\u0435\u0440\u0445\u0435\u0434\u0430 (\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0437\u0430\u043d\u044f\u0442\u044b\u0445 \u0431\u0430\u0439\u0442\u043e\u0432) \u043d\u0430 \u0441\u0442\u0435\u043a\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<h2>sp::static_ptr&lt;T><\/h2>\n<p>\u0418\u043c\u0435\u044f \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u0438\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c stack-only \u0430\u043d\u0430\u043b\u043e\u0433 <code>std::unique_ptr&lt;T><\/code>, \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u0438\u0441\u043a\u0430\u0442\u044c \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0438\u0434\u0435\u044f, \u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u044b, \u043b\u0435\u0436\u0438\u0442 \u043d\u0430 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>\u041f\u0440\u0438\u0434\u0443\u043c\u0430\u0432 \u0442\u0430\u043a\u0438\u0435 \u0441\u043b\u043e\u0432\u0430 \u043a\u0430\u043a <code>stack_ptr<\/code>, <code>static_ptr<\/code> \u0438 \u043f\u0440., \u0438 \u043f\u043e\u0438\u0441\u043a\u0430\u0432 \u0438\u0445 \u043d\u0430 GitHub, \u044f \u043d\u0430\u0448\u0435\u043b \u0432\u043c\u0435\u043d\u044f\u0435\u043c\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 ceph<a href=\"https:\/\/github.com\/ceph\/ceph\" rel=\"noopener noreferrer nofollow\"><sup>6<\/sup><\/a>, \u0432 <code>ceph\/static_ptr.h<\/code><a href=\"https:\/\/github.com\/ceph\/ceph\/blob\/master\/src\/common\/static_ptr.h\" rel=\"noopener noreferrer nofollow\"><sup>7<\/sup><\/a> \u0438 \u0443\u0432\u0438\u0434\u0435\u043b \u0442\u0430\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0438\u0434\u0435\u0438. \u0412\u043f\u0440\u043e\u0447\u0435\u043c, \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043c\u0430\u043b\u043e \u0433\u0434\u0435, \u0438 \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0435\u0441\u0442\u044c \u0440\u044f\u0434 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u043c\u0430\u0445\u043e\u0432.<\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a &#8212; \u0435\u0441\u0442\u044c \u0441\u0430\u043c \u0431\u0443\u0444\u0435\u0440 \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 (\u0432 \u0432\u0438\u0434\u0435 <code>std::aligned_storage<\/code>); \u0438 \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0440\u0443\u043b\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c: \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0434\u0435\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u043e\u0433\u043e \u0442\u0438\u043f\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0435\u0439\u0447\u0430\u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0432 <code>static_ptr<\/code>.<\/p>\n<figure class=\"\"> \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430 (\u0431\u0443\u0444\u0435\u0440 \u043d\u0430 32 \u0431\u0430\u0439\u0442\u0430)&#187; title=&#187;sp::static_ptr&lt;IEngine> \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430 (\u0431\u0443\u0444\u0435\u0440 \u043d\u0430 32 \u0431\u0430\u0439\u0442\u0430)&#187; width=&#187;387&#8243; height=&#187;203&#8243; data-src=&#187;https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/28c\/9af\/42d\/28c9af42d324c26c4e839d1a322bf6ac.png&#187;\/><figcaption>sp::static_ptr&lt;IEngine> \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430 (\u0431\u0443\u0444\u0435\u0440 \u043d\u0430 32 \u0431\u0430\u0439\u0442\u0430)<\/figcaption><\/figure>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f: \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043b\u043e\u0436\u0435\u043d move?<\/h2>\n<p>\u0417\u0434\u0435\u0441\u044c \u044f \u043e\u043f\u0438\u0448\u0443 \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0445 \u043a\u0430\u043c\u043d\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0432\u0441\u043f\u043b\u044b\u0442\u044c.<\/p>\n<p>\u0421\u0430\u043c \u043a\u043b\u0430\u0441\u0441 <code>static_ptr<\/code> \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 namespace <code>sp<\/code> (\u043e\u0442 <strong>s<\/strong>tatic <strong>p<\/strong>ointer).<\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432, \u0443\u043c\u043d\u044b\u0445 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439, \u0438 \u043f\u0440\u043e\u0447\u0438\u0445 \u0432\u0435\u0449\u0435\u0439 &#8212; \u044d\u0442\u043e \u0432\u043e\u043e\u0431\u0449\u0435 \u043e\u0434\u043d\u0438 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c \u043d\u0430 C++, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0437\u0430\u0434\u0443\u043c\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u0434 \u0432\u0435\u0449\u0430\u043c\u0438, \u043f\u0440\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u043d\u0435 \u043f\u043e\u0434\u043e\u0437\u0440\u0435\u0432\u0430\u044e\u0442.<\/p>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0432\u044b\u0437\u0432\u0430\u0442\u044c move-\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0443\u0447\u0430\u0441\u0442\u043a\u0430 \u043f\u0430\u043c\u044f\u0442\u0438 \u0432 \u0434\u0440\u0443\u0433\u043e\u0439. \u041c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cpp\">template &lt;typename T> struct move_constructer {     static void call(T* lhs, T* rhs) {         new (lhs) T(std::move(*rhs));     } }; \/\/ call `move_constructer&lt;T>::call(dst, src);`<\/code><\/pre>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u043a\u043b\u0430\u0441\u0441 <code>T<\/code> \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 move-\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430?<\/p>\n<p>\u0415\u0441\u0442\u044c \u0448\u0430\u043d\u0441, \u0447\u0442\u043e <code>T<\/code> \u0438\u043c\u0435\u0435\u0442 move-\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u044f, \u0442\u043e\u0433\u0434\u0430 \u043d\u0430\u0434\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e. \u0415\u0441\u043b\u0438 \u0438 \u0435\u0433\u043e \u043d\u0435\u0442, \u0442\u043e \u043d\u0430\u0434\u043e &#171;\u0441\u043b\u043e\u043c\u0430\u0442\u044c&#187; \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044e.<\/p>\n<p>\u0427\u0435\u043c \u043d\u043e\u0432\u0435\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 C++, \u0442\u0435\u043c \u043b\u0435\u0433\u0447\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434 \u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0432\u0435\u0449\u0435\u0439. \u041f\u043e\u043b\u0443\u0447\u0438\u043c \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434 (\u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 C++<strong>17<\/strong>):<\/p>\n<pre><code class=\"cpp\">template &lt;typename T> struct move_constructer {     static void call(T* lhs, T* rhs) {         if constexpr (std::is_move_constructible_v&lt;T>) {             new (lhs) T(std::move(*rhs));         } else if constexpr (std::is_default_constructible_v&lt;T> &amp;&amp; std::is_move_assignable_v&lt;T>) {             new (lhs) T();             *lhs = std::move(*rhs);         } else {             []&lt;bool flag = false>(){ static_assert(flag, \"move constructor disabled\"); }();         }     } };<\/code><\/pre>\n<p>(\u043d\u0430 10 \u0441\u0442\u0440\u043e\u043a\u0435 \u0441\u043b\u043e\u043c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0432 \u0432\u0438\u0434\u0435 <code>static_assert<\/code> \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441 \u0445\u0430\u043a\u043e\u043c<a href=\"https:\/\/stackoverflow.com\/a\/64354296\" rel=\"noopener noreferrer nofollow\"><sup>8<\/sup><\/a>)<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u043d\u0435\u043f\u043b\u043e\u0445\u043e \u0431\u044b \u0435\u0449\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c <code>noexcept<\/code>-\u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u043a\u043e\u0433\u0434\u0430 \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u0412 C++<strong>20<\/strong> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434, \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442:<\/p>\n<pre><code class=\"cpp\">template &lt;typename T> struct move_constructer {     static void call(T* lhs, T* rhs)         noexcept (std::is_nothrow_move_constructible_v&lt;T>)         requires (std::is_move_constructible_v&lt;T>)     {         new (lhs) T(std::move(*rhs));     }      static void call(T* lhs, T* rhs)         noexcept (std::is_nothrow_default_constructible_v&lt;T> &amp;&amp; std::is_nothrow_move_assignable_v&lt;T>)         requires (!std::is_move_constructible_v&lt;T> &amp;&amp; std::is_default_constructible_v&lt;T> &amp;&amp; std::is_move_assignable_v&lt;T>)     {         new (lhs) T();         *lhs = std::move(*rhs);     } };<\/code><\/pre>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0441 \u0440\u0430\u0437\u0431\u043e\u0440\u043e\u043c \u043a\u0435\u0439\u0441\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 <code>move_assigner<\/code>. \u041c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0435\u0449\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c <code>copy_constructer<\/code> \u0438 <code>copy_assigner<\/code>, \u043d\u043e \u0432 \u043d\u0430\u0448\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u043d\u0438 \u043d\u0435 \u043d\u0443\u0436\u043d\u044b. \u0412 <code>static_ptr<\/code> \u0431\u0443\u0434\u0443\u0442 \u0443\u0434\u0430\u043b\u0435\u043d\u044b copy constructor \u0438 copy assignment operator (\u043a\u0430\u043a \u0438 \u0432 <code>unique_ptr<\/code>).<\/p>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f: std::type_info \u043d\u0430 \u043a\u043e\u043b\u0435\u043d\u043a\u0435<\/h2>\n<p>\u0425\u043e\u0442\u044f \u0432 <code>static_ptr<\/code> \u043c\u043e\u0436\u0435\u0442 \u043b\u0435\u0436\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043d\u0430\u043c \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e &#171;\u0437\u043d\u0430\u0442\u044c&#187; \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0437\u0430 \u0442\u0438\u043f \u0442\u0430\u043c \u043b\u0435\u0436\u0438\u0442. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0434\u0435\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u043e\u0447\u0438\u0435 \u0432\u0435\u0449\u0438.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u043f\u044b\u0442\u043e\u043a \u044f \u0432\u044b\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0442\u0430\u043a\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 &#8212; \u043d\u0443\u0436\u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 <code>ops<\/code>:<\/p>\n<pre><code class=\"cpp\">struct ops {     using binary_func = void(*)(void* dst, void* src);     using unary_func = void(*)(void* dst);      binary_func move_construct_func;     binary_func move_assign_func;     unary_func destruct_func; };<\/code><\/pre>\n<p>\u0418 \u043f\u0430\u0440\u0430 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 <code>void*<\/code> \u0432 <code>T*<\/code>&#8230;<\/p>\n<pre><code class=\"cpp\">template&lt;typename T, typename Functor> void call_typed_func(void* dst, void* src) {     Functor::call(static_cast&lt;T*>(dst), static_cast&lt;T*>(src)); }  template&lt;typename T> void destruct_func(void* dst) {     static_cast&lt;T*>(dst)->~T(); }<\/code><\/pre>\n<p>\u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0438\u043f\u0430 <code>T<\/code> \u0438\u043c\u0435\u0442\u044c \u0441\u0432\u043e\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 <code>ops<\/code>:<\/p>\n<pre><code class=\"cpp\">template&lt;typename T> static constexpr ops ops_for{     .move_construct_func = &amp;call_typed_func&lt;T, move_constructer&lt;T>>,     .move_assign_func = &amp;call_typed_func&lt;T, move_assigner&lt;T>>,     .destruct_func = &amp;destruct_func&lt;T>, }; using ops_ptr = const ops*;<\/code><\/pre>\n<p><code>static_ptr<\/code> \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 <code>ops_for&lt;T><\/code>, \u0433\u0434\u0435 <code>T<\/code> \u044d\u0442\u043e \u043a\u043b\u0430\u0441\u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0435\u0439\u0447\u0430\u0441 \u043b\u0435\u0436\u0438\u0442 \u0432 <code>static_ptr<\/code>.<\/p>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f: I like to move it, move it<\/h2>\n<p>\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c <code>static_ptr<\/code> \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u043b\u044c\u0437\u044f &#8212; \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u0443\u0432\u0430\u0442\u044c \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 <code>static_ptr<\/code>. \u0412\u044b\u0431\u043e\u0440 \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u043c\u0443\u0432\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0437\u0430 \u0442\u0438\u043f \u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043b\u0435\u0436\u0430\u0442 \u0432 \u044d\u0442\u0438\u0445 \u0434\u0432\u0443\u0445 <code>static_ptr<\/code>:<\/p>\n<ol>\n<li>\n<p>\u041e\u0431\u0430 <code>static_ptr<\/code> \u043f\u0443\u0441\u0442\u044b\u0435 (<code>dst_ops = src_ops = nullptr<\/code>): \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p><code>static_ptr<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0442\u0438\u043f (<code>dst_ops = src_ops<\/code>): \u0434\u0435\u043b\u0430\u0435\u043c <strong>move assign<\/strong> \u0438 \u0440\u0430\u0437\u0440\u0443\u0448\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 <code>src<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>static_ptr<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0442\u0438\u043f\u044b (<code>dst_ops != src_ops<\/code>): \u0440\u0430\u0437\u0440\u0443\u0448\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 <code>dst<\/code>, \u0434\u0435\u043b\u0430\u0435\u043c <strong>move construct<\/strong>, \u0440\u0430\u0437\u0440\u0443\u0448\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 <code>src<\/code>, \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u0435 <code>dst_ops = src_ops<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0442\u0430\u043a\u043e\u0439 \u043c\u0435\u0442\u043e\u0434:<\/p>\n<pre><code class=\"cpp\">\/\/ moving objects using ops static void move_construct(void* dst_buf, ops_ptr&amp; dst_ops,                            void* src_buf, ops_ptr&amp; src_ops) {     if (!src_ops &amp;&amp; !dst_ops) {         \/\/ both object are nullptr_t, do nothing         return;     } else if (src_ops == dst_ops) {         \/\/ objects have the same type, make move         (*src_ops->move_assign_func)(dst_buf, src_buf);         (*src_ops->destruct_func)(src_buf);         src_ops = nullptr;     } else {         \/\/ objects have different type         \/\/ delete the old object         if (dst_ops) {             (*dst_ops->destruct_func)(dst_buf);             dst_ops = nullptr;         }         \/\/ construct the new object         if (src_ops) {             (*src_ops->move_construct_func)(dst_buf, src_buf);             (*src_ops->destruct_func)(src_buf);         }         dst_ops = src_ops;         src_ops = nullptr;     } }<\/code><\/pre>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f: \u0440\u0430\u0437\u043c\u0435\u0440 \u0431\u0443\u0444\u0435\u0440\u0430 \u0438 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435<\/h2>\n<p>\u0421\u0435\u0439\u0447\u0430\u0441 \u043d\u0430\u0434\u043e \u0440\u0435\u0448\u0438\u0442\u044c, \u043a\u0430\u043a\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0431\u0443\u0444\u0435\u0440\u0430 \u0438 \u043a\u0430\u043a\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435<a href=\"https:\/\/en.cppreference.com\/w\/c\/language\/object\" rel=\"noopener noreferrer nofollow\"><sup>9<\/sup><\/a>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e <code>std::aligned_storage<\/code> \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0437\u043d\u0430\u0442\u044c \u044d\u0442\u0438 \u0434\u0432\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430-\u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0442\u044c \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430-\u043f\u0440\u0435\u0434\u043a\u0430<a href=\"https:\/\/godbolt.org\/z\/cbjoo3v59\" rel=\"noopener noreferrer nofollow\"><sup>10<\/sup><\/a>. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u044b\u0432\u0430\u0435\u0442. \u0412 \u044d\u0442\u043e\u043c \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0442\u0438\u043f <code>std::max_align_t<\/code><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/types\/max_align_t\" rel=\"noopener noreferrer nofollow\"><sup>11<\/sup><\/a>:<\/p>\n<pre><code class=\"cpp\">static constexpr std::size_t align = alignof(std::max_align_t);<\/code><\/pre>\n<p>\u041d\u0430 \u043c\u043e\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 16, \u043d\u043e \u0433\u0434\u0435-\u0442\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041a\u0441\u0442\u0430\u0442\u0438, \u043f\u0430\u043c\u044f\u0442\u044c \u0438\u0437 \u043a\u0443\u0447\u0438 (\u0438\u0437 <code>malloc<\/code>) \u0442\u043e\u0436\u0435 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u043c\u0443 alignment, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.<\/p>\n<p>\u0414\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0431\u0443\u0444\u0435\u0440\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 16 \u0431\u0430\u0439\u0442 \u0438\u043b\u0438 \u0432 <code>sizeof(T)<\/code> &#8212; \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435.<\/p>\n<pre><code class=\"cpp\">template&lt;typename T> struct static_ptr_traits {     static constexpr std::size_t buffer_size = std::max(static_cast&lt;std::size_t>(16), sizeof(T)); };<\/code><\/pre>\n<p>\u041f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043d\u0430 \u0441\u0432\u043e\u044e \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043c\u0435\u0449\u0430\u043b\u0438\u0441\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0432\u0441\u0435\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432-\u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u043e\u0432. \u0416\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0432 \u0432\u0438\u0434\u0435 \u043c\u0430\u043a\u0440\u043e\u0441\u0430, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0438\u0441\u0430\u0442\u044c. \u041c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u043c\u0430\u043a\u0440\u043e\u0441 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0431\u0443\u0444\u0435\u0440\u0430 \u0432 \u043e\u0434\u043d\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435:<\/p>\n<pre><code class=\"cpp\">#define STATIC_PTR_BUFFER_SIZE(Tp, size)                   \\ namespace sp {                                             \\<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-333123","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/333123","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=333123"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/333123\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=333123"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=333123"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=333123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}