{"id":100635,"date":"2019-01-04T07:00:00","date_gmt":"2019-01-04T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=100635"},"modified":"2019-03-13T00:07:18","modified_gmt":"2019-03-13T07:07:18","slug":"20190104-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190104-00\/?p=100635","title":{"rendered":"A trick for keeping an object alive in a C++ lambda while still being able to use the <CODE>this<\/CODE> keyword to refer to it"},"content":{"rendered":"<p>You may want to capture your <code>this<\/code> pointer into a C++ lambda, but that captures the raw pointer. If you need to extend the object&#8217;s lifetime, you will need to capture a strong reference. For plain C++ code, this would be a <code>std::shared_<\/code><code>ptr<\/code>. For COM objects, this is usually some sort of smart pointer class like <code>ATL::<\/code><code>CComPtr<\/code>, <code>Microsoft::<\/code><code>WRL::<\/code><code>ComPtr<\/code>, or <code>winrt::<\/code><code>com_ptr<\/code>. <\/p>\n<pre>\n  \/\/ std::shared_ptr\n  auto callback = [self = shared_from_this()]() {\n    self-&gt;DoSomething(self-&gt;m_value);\n    self-&gt;DoSomethingElse();\n   };\n\n  \/\/ WRL::ComPtr\n  auto callback = [self =\n                   Microsoft::WRL::ComPtr&lt;ThisClass&gt;(this)]() {\n    self-&gt;DoSomething(self-&gt;m_value);\n    self-&gt;DoSomethingElse();\n  };\n\n  \/\/ ATL::CComPtr\n  auto callback = [self =\n                   ATL::CComPtr&lt;ThisClass&gt;(this)]() {\n    self-&gt;DoSomething(self-&gt;m_value);\n    self-&gt;DoSomethingElse();\n  };\n\n  \/\/ winrt::com_ptr\n  template&lt;typename T&gt;\n  auto to_com_ptr(T* p) noexcept\n  {\n    winrt::com_ptr&lt;T&gt; ptr;\n    ptr.copy_from(p);\n    return ptr;\n  }\n\n  auto callback = [self = to_com_ptr(this)] {\n    self-&gt;DoSomething(self-&gt;m_value);\n    self-&gt;DoSomethingElse();\n  };\n<\/pre>\n<p>A common pattern for the &#8220;capture a strong reference to yourself&#8221; is to capture both a strong reference and a raw <code>this<\/code>. The strong reference keeps the <code>this<\/code> alive, and you use the <code>this<\/code> for convenient access to members. <\/p>\n<pre>\n  \/\/ std::shared_ptr\n  auto callback = [<font COLOR=\"blue\">lifetime<\/font> = std::shared_from_this(this),\n                   <font COLOR=\"blue\">this<\/font>]() {\n    DoSomething(m_value);  <font COLOR=\"blue\">\/\/ was self-&gt;DoSomething(self-&gt;m_value);<\/font>\n    DoSomethingElse();     <font COLOR=\"blue\">\/\/ was self-&gt;DoSomethingElse();<\/font>\n   };\n\n  \/\/ WRL::ComPtr\n  auto callback = [<font COLOR=\"blue\">lifetime<\/font> =\n                   Microsoft::WRL::ComPtr&lt;ThisClass&gt;(this),\n                   <font COLOR=\"blue\">this<\/font>]() {\n    DoSomething(m_value);  <font COLOR=\"blue\">\/\/ was self-&gt;DoSomething(self-&gt;m_value);<\/font>\n    DoSomethingElse();     <font COLOR=\"blue\">\/\/ was self-&gt;DoSomethingElse();<\/font>\n  };\n\n  \/\/ ATL::CComPtr\n  auto callback = [<font COLOR=\"blue\">lifetime<\/font> =\n                   ATL::CComPtr&lt;ThisClass&gt;(this),\n                   <font COLOR=\"blue\">this<\/font>]() {\n    DoSomething(m_value);  <font COLOR=\"blue\">\/\/ was self-&gt;DoSomething(self-&gt;m_value);<\/font>\n    DoSomethingElse();     <font COLOR=\"blue\">\/\/ was self-&gt;DoSomethingElse();<\/font>\n  };\n\n  \/\/ winrt::com_ptr\n  auto callback = [<font COLOR=\"blue\">lifetime<\/font> = to_com_ptr(this),\n                   <font COLOR=\"blue\">this<\/font>]() {\n    DoSomething(m_value);  <font COLOR=\"blue\">\/\/ was self-&gt;DoSomething(self-&gt;m_value);<\/font>\n    DoSomethingElse();     <font COLOR=\"blue\">\/\/ was self-&gt;DoSomethingElse();<\/font>\n  };\n<\/pre>\n<p>I like to give the captured strong reference a name like <code>lifetime<\/code> to emphasize that its purpose is to extend the lifetime of the <code>this<\/code> pointer. Otherwise, somebody might be tempted to &#8220;optimize&#8221; out the seemingly-unused variable. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Capture it twice, once for the money, and once for the show.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-100635","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Capture it twice, once for the money, and once for the show.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100635","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=100635"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100635\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=100635"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=100635"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=100635"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}