{"id":5078,"date":"2016-12-14T20:51:28","date_gmt":"2016-12-14T20:51:28","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/std-weak-ptr\/"},"modified":"2023-06-26T12:32:15","modified_gmt":"2023-06-26T12:32:15","slug":"std-weak-ptr","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/std-weak-ptr\/","title":{"rendered":"std::weak_ptr"},"content":{"rendered":"<p><span style=\"font-family: courier new,courier;\"><a href=\"https:\/\/www.modernescpp.com\/index.php\/std-unique-ptr\">std::unique_ptr<\/a><\/span> models the concept of exclusive ownership, <span style=\"font-family: courier new,courier;\"><a href=\"https:\/\/www.modernescpp.com\/index.php\/std-shared-ptr\">std::shared_ptr<\/a><\/span> the concept of shared ownership. If I stick to this picture then <span style=\"font-family: courier new,courier;\">std::weak_ptr<\/span> models the concept of temporary ownership because it borrows the resource from a <span style=\"font-family: courier new,courier;\">std::shared_ptr.<\/span> There is one dominant reason for having a <span style=\"font-family: courier new,courier;\">std::weak_ptr<\/span> in C++: breaking of cyclic references of <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span>&#8216;s. <span style=\"font-family: courier new,courier;\"><\/span><\/p>\n<p><!--more--><\/p>\n<p>If you study the interface of the smart pointer <span style=\"font-family: courier new,courier;\">std::weak_ptr<\/span>, you will recognize: the <span style=\"font-family: courier new,courier;\">std::weak_ptr<\/span> is not so smart. <span style=\"font-family: courier new,courier;\">std::weak_ptr<\/span> has a minimal interface.<\/p>\n<h2>The interface<\/h2>\n<p><span style=\"font-family: courier new,courier;\">std::weak_ptr<\/span> doesn&#8217;t change &#8211; in opposite to the <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> &#8211; the reference counter of the shared variable. Have a look.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\n31\r\n32\r\n33\r\n34\r\n35\r\n36<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ weakPtr.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;memory&gt;<\/span>\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n\r\n  std::cout &lt;&lt; std::boolalpha &lt;&lt; std::endl;\r\n\r\n  <span style=\"color: #0000ff;\">auto<\/span> sharedPtr=std::make_shared&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;(2011);\r\n  std::weak_ptr&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; weakPtr(sharedPtr);\r\n  \r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"weakPtr.use_count(): \"<\/span> &lt;&lt; weakPtr.use_count() &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"sharedPtr.use_count(): \"<\/span> &lt;&lt; sharedPtr.use_count() &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"weakPtr.expired(): \"<\/span> &lt;&lt; weakPtr.expired() &lt;&lt; std::endl;\r\n\r\n  <span style=\"color: #0000ff;\">if<\/span>( std::shared_ptr&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; sharedPtr1 = weakPtr.lock() ) {\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"*sharedPtr: \"<\/span> &lt;&lt; *sharedPtr &lt;&lt; std::endl;\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"sharedPtr1.use_count(): \"<\/span> &lt;&lt; sharedPtr1.use_count() &lt;&lt; std::endl;\r\n  }\r\n  <span style=\"color: #0000ff;\">else<\/span>{\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Don't get the resource!\"<\/span> &lt;&lt; std::endl;\r\n  }\r\n\r\n  weakPtr.reset();\r\n  <span style=\"color: #0000ff;\">if<\/span>( std::shared_ptr&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; sharedPtr1 = weakPtr.lock() ) {\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"*sharedPtr: \"<\/span> &lt;&lt; *sharedPtr &lt;&lt; std::endl;\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"sharedPtr1.use_count(): \"<\/span> &lt;&lt; sharedPtr1.use_count() &lt;&lt; std::endl;\r\n  }\r\n  <span style=\"color: #0000ff;\">else<\/span>{\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Don't get the resource!\"<\/span> &lt;&lt; std::endl;\r\n  }\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>I create in line 11 a <span style=\"font-family: courier new,courier;\">std::weak_ptr<\/span> which borrows the resource from the <span style=\"font-family: courier new,courier;\">std::shared_ptr.<\/span> The output of the program shows that the reference counter is 1 (lines 13 and 14). That means in particular that <span style=\"font-family: courier new,courier;\">std::weak<\/span> doesn&#8217;t increment the counter. The call <span style=\"font-family: courier new,courier;\">weakPtr.expired()<\/span> checks if the resource was already deleted. That is equivalent to the expression <span style=\"font-family: courier new,courier;\">weakPtr.use_count() == 0.<\/span> If the <span style=\"font-family: courier new,courier;\">std::weak_ptr<\/span> shared temporary a resource, you can use <span style=\"font-family: courier new,courier;\">weakPtr.lock()<\/span> to create a <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> out of it. Now, the reference counter will be increased to 2 (line 18). After resetting the <span style=\"font-family: courier new,courier;\">weakPtr<\/span> (line 25), the call <span style=\"font-family: courier new,courier;\">weakPtr.lock()<\/span> fails.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5075\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/12\/weakPtr.png\" alt=\"weakPtr\" style=\"margin: 15px;\" width=\"368\" height=\"258\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/12\/weakPtr.png 368w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/12\/weakPtr-300x210.png 300w\" sizes=\"auto, (max-width: 368px) 100vw, 368px\" \/><\/p>\n<p>That was almost the whole story of the <span style=\"font-family: courier new,courier;\">std::weak_ptr.<\/span> Almost, because the <span style=\"font-family: courier new,courier;\">std::weak_ptr<\/span> has an extraordinary job. It helps to break cyclic references of <span style=\"font-family: courier new,courier;\">std::shared_ptr&#8217;s.<\/span><\/p>\n<\/p>\n<h2>Cyclic references<\/h2>\n<p>You will get cyclic references of <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> if the <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> reference each other.<\/p>\n<h3>The issue<\/h3>\n<p>If you have a cyclic reference of <span style=\"font-family: courier new,courier;\">std::shared_ptr,<\/span> the reference counter will never become 0. Therefore, the resource will automatically be deleted. But that is precisely the reason, why we use <span style=\"font-family: courier new,courier;\">std::shared_ptr&#8217;<\/span>s. Need an example?<\/p>\n<p>There are two cycles in the graphic. First, between the mother and her daughter; second, between the mother and her son. The subtle difference is, however, that the mother references her daughter with a <span style=\"font-family: courier new,courier;\">std::weak_ptr.<\/span> Therefore, the <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> cycle is broken.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5076\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/12\/cycle.jpg\" alt=\"cycle\" width=\"500\" height=\"321\" style=\"margin: 15px;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/12\/cycle.jpg 936w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/12\/cycle-300x193.jpg 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/12\/cycle-768x493.jpg 768w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>If you don&#8217;t like pictures, here is the corresponding source code.<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\n31\r\n32\r\n33\r\n34\r\n35\r\n36\r\n37\r\n38\r\n39\r\n40\r\n41\r\n42\r\n43\r\n44\r\n45\r\n46\r\n47\r\n48\r\n49<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ cycle.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;memory&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">struct<\/span> Son;\r\n<span style=\"color: #0000ff;\">struct<\/span> Daughter;\r\n\r\n<span style=\"color: #0000ff;\">struct<\/span> Mother{\r\n  ~Mother(){\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Mother gone\"<\/span> &lt;&lt; std::endl;\r\n  }\r\n  <span style=\"color: #2b91af;\">void<\/span> setSon(<span style=\"color: #0000ff;\">const<\/span> std::shared_ptr&lt;Son&gt; s ){\r\n    mySon=s;\r\n  }\r\n  <span style=\"color: #2b91af;\">void<\/span> setDaughter(<span style=\"color: #0000ff;\">const<\/span> std::shared_ptr&lt;Daughter&gt; d ){\r\n    myDaughter=d;\r\n  }\r\n  std::shared_ptr&lt;<span style=\"color: #0000ff;\">const<\/span> Son&gt; mySon;\r\n  std::weak_ptr&lt;<span style=\"color: #0000ff;\">const<\/span> Daughter&gt; myDaughter;\r\n};\r\n\r\n<span style=\"color: #0000ff;\">struct<\/span> Son{\r\n  Son(std::shared_ptr&lt;Mother&gt; m):myMother(m){}\r\n  ~Son(){\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Son gone\"<\/span> &lt;&lt; std::endl;\r\n  }\r\n  std::shared_ptr&lt;<span style=\"color: #0000ff;\">const<\/span> Mother&gt; myMother;\r\n};\r\n\r\n<span style=\"color: #0000ff;\">struct<\/span> Daughter{\r\n  Daughter(std::shared_ptr&lt;Mother&gt; m):myMother(m){}\r\n  ~Daughter(){\r\n    std::cout &lt;&lt; <span style=\"color: #a31515;\">\"Daughter gone\"<\/span> &lt;&lt; std::endl;\r\n  }\r\n  std::shared_ptr&lt;<span style=\"color: #0000ff;\">const<\/span> Mother&gt; myMother;\r\n};\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n  std::cout &lt;&lt; std::endl;\r\n  {\r\n    std::shared_ptr&lt;Mother&gt; mother= std::shared_ptr&lt;Mother&gt;( <span style=\"color: #0000ff;\">new<\/span> Mother);\r\n    std::shared_ptr&lt;Son&gt; son= std::shared_ptr&lt;Son&gt;( <span style=\"color: #0000ff;\">new<\/span> Son(mother) );\r\n    std::shared_ptr&lt;Daughter&gt; daughter= std::shared_ptr&lt;Daughter&gt;( <span style=\"color: #0000ff;\">new<\/span> Daughter(mother) );\r\n    mother-&gt;setSon(son);\r\n    mother-&gt;setDaughter(daughter);\r\n  }\r\n  std::cout &lt;&lt; std::endl;\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Thanks to the artificial scope in lines 41 &#8211; 47, the lifetime of the <span style=\"font-family: courier new,courier;\">mother,<\/span> the <span style=\"font-family: courier new,courier;\">son,<\/span> and the <span style=\"font-family: courier new,courier;\">daughter<\/span> is limited. Or to say it the other way around. <span style=\"font-family: courier new,courier;\">Mother,<\/span> <span style=\"font-family: courier new,courier;\">son,<\/span> and <span style=\"font-family: courier new,courier;\">daughter<\/span> go out of scope, and therefore the destructor of the class <span style=\"font-family: courier new,courier;\">Mother<\/span> (lines 10 &#8211; 12), <span style=\"font-family: courier new,courier;\">Son<\/span> (lines 25 &#8211; 27), and <span style=\"font-family: courier new,courier;\">Daughter<\/span> (lines 33 &#8211; 35) should automatically be invoked.<\/p>\n<p>Should, because only the destructor of the class <span style=\"font-family: courier new,courier;\">Daughter<\/span> is called.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5077\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/12\/cycle.png\" alt=\"cycle\" style=\"margin: 15px;\" width=\"368\" height=\"186\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/12\/cycle.png 368w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/12\/cycle-300x152.png 300w\" sizes=\"auto, (max-width: 368px) 100vw, 368px\" \/><\/p>\n<p>The graphic or the source code shows it. We have a cyclic reference of <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> between <span style=\"font-family: courier new,courier;\">mother<\/span> and <span style=\"font-family: courier new,courier;\">son.<\/span> Therefore, the reference counter is always greater than 0, and the destructor will not automatically be invoked. That observation is not true for <span style=\"font-family: courier new,courier;\">mother<\/span> and <span style=\"font-family: courier new,courier;\">daughter.<\/span> If <span style=\"font-family: courier new,courier;\">daughter<\/span> goes out of scope, the reference counter of the <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> <span style=\"font-family: courier new,courier;\">myMother<\/span> (line 36) becomes 0 and the resource will automatically be deleted.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>The Standard Template Library (STL) containers automatically manage their memory. This holds true for the associative and the sequential container. Especially powerful is the automatic memory management of the sequential container <span style=\"font-family: courier new,courier;\">std::vector<\/span> and <span style=\"font-family: courier new,courier;\">std::string.<\/span> Although the <span style=\"font-family: courier new,courier;\">std::string<\/span> is not a sequential container of the STL, it has much in common with a <span style=\"font-family: courier new,courier;\">std::vector&lt;char&gt;.<\/span> So, there are many reasons for me to have in the <a href=\"https:\/\/www.modernescpp.com\/index.php\/automatic-memory-management-with-containers\">next post <\/a>a closer look at the memory management of both containers.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p><span class=\"h3\"><\/span><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>std::unique_ptr models the concept of exclusive ownership, std::shared_ptr the concept of shared ownership. If I stick to this picture then std::weak_ptr models the concept of temporary ownership because it borrows the resource from a std::shared_ptr. There is one dominant reason for having a std::weak_ptr in C++: breaking of cyclic references of std::shared_ptr&#8216;s.<\/p>\n","protected":false},"author":21,"featured_media":5075,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[364],"tags":[498,400,399,511],"class_list":["post-5078","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-embedded","tag-memory","tag-shared_ptr","tag-smart-pointers","tag-weak_ptr"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5078","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=5078"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5078\/revisions"}],"predecessor-version":[{"id":6913,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5078\/revisions\/6913"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5075"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5078"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5078"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5078"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}