{"id":5352,"date":"2017-12-01T20:34:22","date_gmt":"2017-12-01T20:34:22","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-to-resource-management\/"},"modified":"2023-06-26T12:01:15","modified_gmt":"2023-06-26T12:01:15","slug":"c-core-guidelines-rules-to-resource-management","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-to-resource-management\/","title":{"rendered":"C++ Core Guidelines: Rules about Resource Management"},"content":{"rendered":"<p>This and the following posts will probably be about the most critical concern in programming: resource management. The C++ Core Guidelines have rules for resource management in general but also rules for allocation and deallocation and smart pointers in particular. Today I will begin with the general rules of resource management.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5351\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/12\/photo-montage-1548599_640.png\" alt=\"photo montage 1548599 640\" width=\"640\" height=\"426\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/12\/photo-montage-1548599_640.png 640w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/12\/photo-montage-1548599_640-300x200.png 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/p>\n<p>At first. What is a resource? A resource is something that you have to manage. That means you must acquire and release it because resources are limited, or you must protect them. You can only have a limited amount of memory, sockets, processes, or threads; only one process can write a shared file, or one thread can write a shared variable at one point. If you don&#8217;t follow the protocol, many issues are possible.<\/p>\n<p>Your system may<\/p>\n<ul>\n<li>become out of memory because you leak memory.<\/li>\n<li>have a data race because you forget to acquire a lock before you use the shared variable.<\/li>\n<li>have a deadlock because you are acquiring and releasing a few shared variables in a different sequence.<\/li>\n<\/ul>\n<p>The issues with data race and data locks are not unique to shared variables. For example, you can have the same issues with files.<\/p>\n<p>If you think about resource management, it all boils down to one key point: ownership. So let me give you first the big picture before I write about the rules.<\/p>\n<p>What I like in particular about modern C++ is that we can directly express our intention about ownership in code.<\/p>\n<ul>\n<li><strong>Local objects<\/strong>. The C++ runtime, as the owner, automatically manages the lifetime of these resources. The same holds for global objects or members of a class. The guidelines call them scoped objects.<\/li>\n<li><strong>References<\/strong>: I&#8217;m not the owner. I only borrowed resources that cannot be empty.<\/li>\n<li><strong>Raw pointers<\/strong>: I&#8217;m not the owner. I only borrowed the resource that can be can be empty. I must not delete the resource.<\/li>\n<li><strong><span style=\"font-family: courier new,courier;\">std::unique_ptr<\/span><\/strong>: I&#8217;m the exclusive owner of the resource. I may explicitly release the resource.<\/li>\n<li><strong><span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span><\/strong>: I share the resource with other shared ptr. I may explicitly release my shared ownership.<\/li>\n<li><strong><span style=\"font-family: courier new,courier;\">std::weak_ptr<\/span><\/strong>: I&#8217;m not the owner of the resource but may temporarily become the shared owner by using the method <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/memory\/weak_ptr\/lock\"><span style=\"font-family: courier new,courier;\">std::weak_ptr::lock<\/span><\/a>.<\/li>\n<\/ul>\n<p>Compare this fine-grained ownership semantic to just a raw pointer. Now you know, what I like about modern C++.<\/p>\n<p>Here is a summary of the rules for resource management.<\/p>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-raii\">R.1: Manage resources automatically using resource handles and RAII (Resource Acquisition Is Initialization)<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-use-ptr\">R.2: In interfaces, use raw pointers to denote individual objects (only)<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-ptr\">R.3: A raw pointer (a <code class=\"highlighter-rouge no-highlight\">T*<\/code>) is non-owning<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-ref\">R.4: A raw reference (a <code class=\"highlighter-rouge no-highlight\">T&amp;<\/code>) is non-owning<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-scoped\">R.5: Prefer scoped objects, don\u2019t heap-allocate unnecessarily<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-global\">R.6: Avoid non-<code class=\"highlighter-rouge no-highlight\">const<\/code> global variables<\/a><\/li>\n<\/ul>\n<p>Let&#8217;s look at each of them in detail.<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-raii\">R.1: Manage resources automatically using resource handles and RAII (Resource Acquisition Is Initialization)<\/a><\/h3>\n<p>The idea is quite simple. You create a kind of proxy object for your resource. The proxy&#8217;s constructor will acquire the resource, and the destructor will release the resource. The key idea of RAII is that the C++ runtime is the owner of the <strong>local object<\/strong> and, therefore, of the resource.<\/p>\n<p>Two typical examples of RAII in modern C++ are smart pointers and locks. Smart pointer takes care of their memory, and locks care for their mutexes.<\/p>\n<p>The following class <span style=\"font-family: courier new,courier;\">ResourceGuard<\/span> models RAII.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ raii.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;new&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;string&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">ResourceGuard<\/span>{\r\n  <span style=\"color: #9999ff;\">private:<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">const<\/span> std<span style=\"color: #555555;\">::<\/span>string resource;\r\n  <span style=\"color: #9999ff;\">public:<\/span>\r\n    ResourceGuard(<span style=\"color: #006699; font-weight: bold;\">const<\/span> std<span style=\"color: #555555;\">::<\/span>string<span style=\"color: #555555;\">&amp;<\/span> res)<span style=\"color: #555555;\">:<\/span>resource(res){\r\n      std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Acquire the \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> resource <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\".\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span>  std<span style=\"color: #555555;\">::<\/span>endl;\r\n    }\r\n    <span style=\"color: #555555;\">~<\/span>ResourceGuard(){\r\n      std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Release the \"<\/span><span style=\"color: #555555;\">&lt;&lt;<\/span> resource <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\".\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    }\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n  ResourceGuard resGuard1{<span style=\"color: #cc3300;\">\"memoryBlock1\"<\/span>};                  <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">Before local scope\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n  {\r\n    ResourceGuard resGuard2{<span style=\"color: #cc3300;\">\"memoryBlock2\"<\/span>};                <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n  }\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"After local scope\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n  \r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n  \r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">Before try-catch block\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n  try{\r\n      ResourceGuard resGuard3{<span style=\"color: #cc3300;\">\"memoryBlock3\"<\/span>};              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n      <span style=\"color: #006699; font-weight: bold;\">throw<\/span> std<span style=\"color: #555555;\">::<\/span>bad_alloc();\r\n  }   \r\n  <span style=\"color: #006699; font-weight: bold;\">catch<\/span> (std<span style=\"color: #555555;\">::<\/span>bad_alloc<span style=\"color: #555555;\">&amp;<\/span> e){\r\n      std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> e.what();\r\n  }\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">After try-catch block\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n  \r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>It makes no difference if the lifetime of instances of <span style=\"font-family: courier new,courier;\">ResourceGuard<\/span> ends regularly (1) and (2) or irregularly (3). The destructor of <span style=\"font-family: courier new,courier;\">ResourceGuard<\/span> will always be called. This means the resource will be released.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5101\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/12\/raii.png\" alt=\"raii\" width=\"400\" height=\"326\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/12\/raii.png 456w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/12\/raii-300x245.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>Read my post: Garbage Collection &#8211; No Thanks for more details about the example and RAII. Even Bjarne Stroustrup made a comment.<\/p>\n<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-use-ptr\">R.2: In interfaces, use raw pointers to denote individual objects (only)<\/a><\/h3>\n<p>Raw pointers should not denote arrays because this is very error-prone. This becomes, in particular, true if your function takes a pointer as an argument.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">f<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">*<\/span> p, <span style=\"color: #007788; font-weight: bold;\">int<\/span> n)   <span style=\"color: #0099ff; font-style: italic;\">\/\/ n is the number of elements in p[]<\/span>\r\n{\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    p[<span style=\"color: #ff6600;\">2<\/span>] <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">7<\/span>;   <span style=\"color: #0099ff; font-style: italic;\">\/\/ bad: subscript raw pointer<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>It&#8217;s quite easy to pass the wrong side of the array as an argument.<\/p>\n<p>For arrays, we have containers such as <span style=\"font-family: courier new,courier;\">std::vector<\/span>. A container of the Standard Template Library is an exclusive owner. It acquires and releases its memory automatically.<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-ptr\">R.3: A raw pointer (a <code class=\"highlighter-rouge no-highlight\">T*<\/code>) is non-owning<\/a><\/h3>\n<p>The issue of ownership becomes in particular interesting if you have a factory. A factory is a special function that returns a new object. Now the question is. Should you return a raw pointer, an object, a <span style=\"font-family: courier new,courier;\">std::unique_ptr,<\/span> or a <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span>?<\/p>\n<p>Here are the four variations:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">Widget<span style=\"color: #555555;\">*<\/span> <span style=\"color: #cc00ff;\">makeWidget<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> n){                    \/\/ (1)\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> p <span style=\"color: #555555;\">=<\/span> <span style=\"color: #006699; font-weight: bold;\">new<\/span> Widget{n};\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> p;\r\n}\r\n\r\nWidget <span style=\"color: #cc00ff;\">makeWidget<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> n){                     \/\/ (2)\r\n    Widget g{n};\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> g;\r\n}\r\n\r\nstd<span style=\"color: #555555;\">::<\/span>unique_ptr<span style=\"color: #555555;\">&lt;<\/span>Widget<span style=\"color: #555555;\">&gt;<\/span> makeWidget(<span style=\"color: #007788; font-weight: bold;\">int<\/span> n){    \/\/ (3)\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> u <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>make_unique<span style=\"color: #555555;\">&lt;<\/span>Widget&gt;(n);\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n   <span style=\"color: #006699; font-weight: bold;\">return<\/span> u;\r\n}\r\n\r\nstd<span style=\"color: #555555;\">::<\/span>shared_ptr<span style=\"color: #555555;\">&lt;<\/span>Widget<span style=\"color: #555555;\">&gt;<\/span> makeWidget(<span style=\"color: #007788; font-weight: bold;\">int<\/span> n){    \/\/ (4)\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> s <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>make_shared<span style=\"color: #555555;\">&lt;<\/span>Widget&gt;(n);\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n   <span style=\"color: #006699; font-weight: bold;\">return<\/span> s;\r\n}\r\n\r\n...\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> widget <span style=\"color: #555555;\">=<\/span> makeWidget(<span style=\"color: #ff6600;\">10<\/span>);\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Who should be the owner of the widget? The caller or the callee? I assume you can not answer the question for the pointer in the example. Me too. This means we have no idea who should call delete.<br \/>In contrast, cases (2) to (4) are apparent. In the case of the object or the <span style=\"font-family: courier new,courier;\">std::unique_ptr<\/span>, the caller is the owner. In the case of the <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span>, the caller and the callee share the ownership.<\/p>\n<p>One question remains. Should you go with an object or a smart pointer? Here are my thoughts.<\/p>\n<ul>\n<li>If your factory is polymorphic, such as a virtual constructor, you must use a smart pointer. I have already written about this special use case. Read the details in the post: <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-constructors\">C++ Core Guidelines: Constructors<\/a> (C.50).<\/li>\n<li>If the object is cheap to copy and the caller should be the owner of the widget, use an object. If not cheap to copy, use a <span style=\"font-family: courier new,courier;\">std::unique_ptr.<\/span><\/li>\n<li>If the callee wants to manage the lifetime of the widget, use a <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span><\/li>\n<\/ul>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-ref\">R.4: A raw reference (a <code class=\"highlighter-rouge no-highlight\">T&amp;<\/code>) is non-owning<\/a><\/h3>\n<p>There is nothing to add. A raw reference is non-owning and cannot be empty.<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-scoped\">R.5: Prefer scoped objects, don\u2019t heap-allocate unnecessarily<\/a><\/h3>\n<p>A scoped object is an object with its scope. That may be a local object, a global object, or a member. The C++ runtime takes care of the object. No memory allocation and deallocation are involved, and we can not get a <span style=\"font-family: courier new,courier;\">std::bad_alloc<\/span> exception. To make it simple: If possible, use a scoped object.<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rr-global\">R.6: Avoid non-<code class=\"highlighter-rouge no-highlight\">const<\/code> global variables<\/a><\/h3>\n<p>I often hear: global variables are bad. That is not true. Non-const global variables are bad. There are many reasons for avoiding non-const global variables. Here are a few reasons. I assume, for simplicity reasons, that the functions or objects use non-const global variables.<\/p>\n<ul>\n<li><strong>Encapsulation<\/strong>: Functions or objects could be changed outside of their scope. This means it is pretty challenging to think about your code.<\/li>\n<li><strong>Testability:<\/strong> You can not test your function in isolation. The effect of your function depends on the state of your program.<\/li>\n<li><strong>Refactoring:<\/strong> Refactoring your code is pretty challenging if you can not think about your function in isolation.<\/li>\n<li><strong>Optimization:<\/strong> You can not easily rearrange the function invocations or perform the function invocations on different threads because there may be hidden dependencies.<\/li>\n<li><strong>Concurrency:<\/strong> The necessary condition for having a <a href=\"https:\/\/www.modernescpp.com\/index.php\/race-condition-versus-data-race\">data race<\/a> is a shared, mutable state. Non-const global variables are shared mutable states.<\/li>\n<\/ul>\n<h2>What&#8217;s next?<\/h2>\n<p>In the <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-allocating-and-deallocating\">next post<\/a>, I will write about a very important resource: memory.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This and the following posts will probably be about the most critical concern in programming: resource management. The C++ Core Guidelines have rules for resource management in general but also rules for allocation and deallocation and smart pointers in particular. Today I will begin with the general rules of resource management.<\/p>\n","protected":false},"author":21,"featured_media":5351,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[498],"class_list":["post-5352","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-memory"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5352","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=5352"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5352\/revisions"}],"predecessor-version":[{"id":6849,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5352\/revisions\/6849"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5351"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5352"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5352"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5352"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}