CINXE.COM

May 2013 – Sutter’s Mill

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="profile" href="http://gmpg.org/xfn/11"> <title>May 2013 &#8211; Sutter’s Mill</title> <script type="text/javascript"> WebFontConfig = {"google":{"families":["Alegreya+Sans:r:latin,latin-ext","Noticia+Text:r,i,b,bi:latin,latin-ext"]},"api_url":"https:\/\/fonts-api.wp.com\/css"}; (function() { var wf = document.createElement('script'); wf.src = 'https://s0.wp.com/wp-content/plugins/custom-fonts/js/webfont.js'; wf.type = 'text/javascript'; wf.async = 'true'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(wf, s); })(); </script><style id="jetpack-custom-fonts-css">.wf-active code, .wf-active kbd, .wf-active pre, .wf-active samp{font-family:"Noticia Text",serif}.wf-active body{font-family:"Noticia Text",serif}.wf-active button, .wf-active input, .wf-active select{font-family:"Noticia Text",serif}.wf-active textarea{font-family:"Noticia Text",serif}.wf-active blockquote{font-family:"Noticia Text",serif}.wf-active code, .wf-active kbd, .wf-active pre, .wf-active tt, .wf-active var{font-family:"Noticia Text",serif}.wf-active .button, .wf-active .more-link, .wf-active button:not(.menu-toggle), .wf-active input[type="button"], .wf-active input[type="reset"], .wf-active input[type="submit"], .wf-active .posts-navigation .nav-links a, .wf-active #content #infinite-handle span button{font-family:"Noticia Text",serif}.wf-active input[type="email"], .wf-active input[type="password"], .wf-active input[type="search"], .wf-active input[type="text"], .wf-active input[type="url"], .wf-active textarea{font-family:"Noticia Text",serif}.wf-active .post-navigation{font-family:"Noticia Text",serif}.wf-active .main-navigation{font-family:"Noticia Text",serif}.wf-active .entry-content, .wf-active .entry-summary, .wf-active .page-content{font-family:"Noticia Text",serif}.wf-active .entry-content .subtitle{font-family:"Noticia Text",serif}.wf-active #comments{font-family:"Noticia Text",serif}.wf-active .comment-form label{font-family:"Noticia Text",serif}.wf-active .comment-form span.required{font-family:"Noticia Text",serif}.wf-active .widget_recent_entries span.post-date{font-family:"Noticia Text",serif}.wf-active .site-description{font-family:"Noticia Text",serif}.wf-active .site-posted-on time{font-family:"Noticia Text",serif}.wf-active .page-header:not(.page-header-light) .taxonomy-description{font-family:"Noticia Text",serif}.wf-active .light-text{font-family:"Noticia Text",serif}.wf-active .site-info{font-family:"Noticia Text",serif}.wf-active .sticky-label{font-family:"Noticia Text",serif}.wf-active .post-details, .wf-active .post-details a{font-family:"Noticia Text",serif}.wf-active .page-links{font-family:"Noticia Text",serif}.wf-active .post-edit-link{font-family:"Noticia Text",serif}.wf-active .post-author-card .author-description{font-family:"Noticia Text",serif}.wf-active #tinymce h1, .wf-active #tinymce h2, .wf-active #tinymce h3, .wf-active #tinymce h4, .wf-active #tinymce h5, .wf-active #tinymce h6, .wf-active .comment-content h1, .wf-active .comment-content h2, .wf-active .comment-content h3, .wf-active .comment-content h4, .wf-active .comment-content h5, .wf-active .comment-content h6, .wf-active .entry-content h1, .wf-active .entry-content h2, .wf-active .entry-content h3, .wf-active .entry-content h4, .wf-active .entry-content h5, .wf-active .entry-content h6, .wf-active .entry-summary h1, .wf-active .entry-summary h2, .wf-active .entry-summary h3, .wf-active .entry-summary h4, .wf-active .entry-summary h5, .wf-active .entry-summary h6, .wf-active .widget_text h1, .wf-active .widget_text h2, .wf-active .widget_text h3, .wf-active .widget_text h4, .wf-active .widget_text h5, .wf-active .widget_text h6{font-family:"Alegreya Sans",sans-serif;font-style:normal;font-weight:400}.wf-active h1{font-style:normal;font-weight:400}.wf-active h2{font-style:normal;font-weight:400}.wf-active h3{font-style:normal;font-weight:400}.wf-active h4{font-style:normal;font-weight:400}.wf-active h5{font-style:normal;font-weight:400}.wf-active h6{font-style:normal;font-weight:400}.wf-active blockquote h1, .wf-active blockquote h2, .wf-active blockquote h3, .wf-active blockquote h4{font-family:"Alegreya Sans",sans-serif;font-weight:400;font-style:normal}.wf-active div#jp-relatedposts h3.jp-relatedposts-headline em{font-family:"Alegreya Sans",sans-serif;font-style:normal;font-weight:400}.wf-active .comment-reply-title, .wf-active .comments-title{font-family:"Alegreya Sans",sans-serif;font-weight:400;font-style:normal}.wf-active .image-post-title{font-family:"Alegreya Sans",sans-serif;font-weight:400;font-style:normal}.wf-active .page-header:not(.page-header-light) h1{font-style:normal;font-weight:400}.wf-active .entry-title{font-family:"Alegreya Sans",sans-serif;font-style:normal;font-weight:400}.wf-active #post-cover-image .cover-meta .single-post-title{font-family:"Alegreya Sans",sans-serif;font-style:normal;font-weight:400}.wf-active #hero-header .site-title{font-family:"Alegreya Sans",sans-serif;font-style:normal;font-weight:400}.wf-active .site-header .site-title{font-style:normal;font-weight:400}.wf-active .site-header .site-description{font-style:normal;font-weight:400}</style> <meta name='robots' content='max-image-preview:large' /> <!-- Async WordPress.com Remote Login --> <script id="wpcom_remote_login_js"> var wpcom_remote_login_extra_auth = ''; function wpcom_remote_login_remove_dom_node_id( element_id ) { var dom_node = document.getElementById( element_id ); if ( dom_node ) { dom_node.parentNode.removeChild( dom_node ); } } function wpcom_remote_login_remove_dom_node_classes( class_name ) { var dom_nodes = document.querySelectorAll( '.' + class_name ); for ( var i = 0; i < dom_nodes.length; i++ ) { dom_nodes[ i ].parentNode.removeChild( dom_nodes[ i ] ); } } function wpcom_remote_login_final_cleanup() { wpcom_remote_login_remove_dom_node_classes( "wpcom_remote_login_msg" ); wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_key" ); wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_validate" ); wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_js" ); wpcom_remote_login_remove_dom_node_id( "wpcom_request_access_iframe" ); wpcom_remote_login_remove_dom_node_id( "wpcom_request_access_styles" ); } // Watch for messages back from the remote login window.addEventListener( "message", function( e ) { if ( e.origin === "https://r-login.wordpress.com" ) { var data = {}; try { data = JSON.parse( e.data ); } catch( e ) { wpcom_remote_login_final_cleanup(); return; } if ( data.msg === 'LOGIN' ) { // Clean up the login check iframe wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_key" ); var id_regex = new RegExp( /^[0-9]+$/ ); var token_regex = new RegExp( /^.*|.*|.*$/ ); if ( token_regex.test( data.token ) && id_regex.test( data.wpcomid ) ) { // We have everything we need to ask for a login var script = document.createElement( "script" ); script.setAttribute( "id", "wpcom_remote_login_validate" ); script.src = '/remote-login.php?wpcom_remote_login=validate' + '&wpcomid=' + data.wpcomid + '&token=' + encodeURIComponent( data.token ) + '&host=' + window.location.protocol + '//' + window.location.hostname + '&postid=2070' + '&is_singular='; document.body.appendChild( script ); } return; } // Safari ITP, not logged in, so redirect if ( data.msg === 'LOGIN-REDIRECT' ) { window.location = 'https://wordpress.com/log-in?redirect_to=' + window.location.href; return; } // Safari ITP, storage access failed, remove the request if ( data.msg === 'LOGIN-REMOVE' ) { var css_zap = 'html { -webkit-transition: margin-top 1s; transition: margin-top 1s; } /* 9001 */ html { margin-top: 0 !important; } * html body { margin-top: 0 !important; } @media screen and ( max-width: 782px ) { html { margin-top: 0 !important; } * html body { margin-top: 0 !important; } }'; var style_zap = document.createElement( 'style' ); style_zap.type = 'text/css'; style_zap.appendChild( document.createTextNode( css_zap ) ); document.body.appendChild( style_zap ); var e = document.getElementById( 'wpcom_request_access_iframe' ); e.parentNode.removeChild( e ); document.cookie = 'wordpress_com_login_access=denied; path=/; max-age=31536000'; return; } // Safari ITP if ( data.msg === 'REQUEST_ACCESS' ) { console.log( 'request access: safari' ); // Check ITP iframe enable/disable knob if ( wpcom_remote_login_extra_auth !== 'safari_itp_iframe' ) { return; } // If we are in a "private window" there is no ITP. var private_window = false; try { var opendb = window.openDatabase( null, null, null, null ); } catch( e ) { private_window = true; } if ( private_window ) { console.log( 'private window' ); return; } var iframe = document.createElement( 'iframe' ); iframe.id = 'wpcom_request_access_iframe'; iframe.setAttribute( 'scrolling', 'no' ); iframe.setAttribute( 'sandbox', 'allow-storage-access-by-user-activation allow-scripts allow-same-origin allow-top-navigation-by-user-activation' ); iframe.src = 'https://r-login.wordpress.com/remote-login.php?wpcom_remote_login=request_access&origin=' + encodeURIComponent( data.origin ) + '&wpcomid=' + encodeURIComponent( data.wpcomid ); var css = 'html { -webkit-transition: margin-top 1s; transition: margin-top 1s; } /* 9001 */ html { margin-top: 46px !important; } * html body { margin-top: 46px !important; } @media screen and ( max-width: 660px ) { html { margin-top: 71px !important; } * html body { margin-top: 71px !important; } #wpcom_request_access_iframe { display: block; height: 71px !important; } } #wpcom_request_access_iframe { border: 0px; height: 46px; position: fixed; top: 0; left: 0; width: 100%; min-width: 100%; z-index: 99999; background: #23282d; } '; var style = document.createElement( 'style' ); style.type = 'text/css'; style.id = 'wpcom_request_access_styles'; style.appendChild( document.createTextNode( css ) ); document.body.appendChild( style ); document.body.appendChild( iframe ); } if ( data.msg === 'DONE' ) { wpcom_remote_login_final_cleanup(); } } }, false ); // Inject the remote login iframe after the page has had a chance to load // more critical resources window.addEventListener( "DOMContentLoaded", function( e ) { var iframe = document.createElement( "iframe" ); iframe.style.display = "none"; iframe.setAttribute( "scrolling", "no" ); iframe.setAttribute( "id", "wpcom_remote_login_key" ); iframe.src = "https://r-login.wordpress.com/remote-login.php" + "?wpcom_remote_login=key" + "&origin=aHR0cHM6Ly9oZXJic3V0dGVyLmNvbQ%3D%3D" + "&wpcomid=3379246" + "&time=1740535026"; document.body.appendChild( iframe ); }, false ); </script> <link rel='dns-prefetch' href='//s1.wp.com' /> <link rel='dns-prefetch' href='//s2.wp.com' /> <link rel='dns-prefetch' href='//s0.wp.com' /> <link rel="alternate" type="application/rss+xml" title="Sutter’s Mill &raquo; Feed" href="https://herbsutter.com/feed/" /> <link rel="alternate" type="application/rss+xml" title="Sutter’s Mill &raquo; Comments Feed" href="https://herbsutter.com/comments/feed/" /> <script type="text/javascript"> /* <![CDATA[ */ function addLoadEvent(func) { var oldonload = window.onload; if (typeof window.onload != 'function') { window.onload = func; } else { window.onload = function () { oldonload(); func(); } } } /* ]]> */ </script> <script type="text/javascript"> /* <![CDATA[ */ window._wpemojiSettings = {"baseUrl":"https:\/\/s0.wp.com\/wp-content\/mu-plugins\/wpcom-smileys\/twemoji\/2\/72x72\/","ext":".png","svgUrl":"https:\/\/s0.wp.com\/wp-content\/mu-plugins\/wpcom-smileys\/twemoji\/2\/svg\/","svgExt":".svg","source":{"concatemoji":"https:\/\/s2.wp.com\/wp-includes\/js\/wp-emoji-release.min.js?m=1719498190i&ver=6.7.2-RC1-59780"}}; /*! This file is auto-generated */ !function(i,n){var o,s,e;function c(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(o,JSON.stringify(t))}catch(e){}}function p(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data),r=(e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0),new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data));return t.every(function(e,t){return e===r[t]})}function u(e,t,n){switch(t){case"flag":return n(e,"\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f","\ud83c\udff3\ufe0f\u200b\u26a7\ufe0f")?!1:!n(e,"\ud83c\uddfa\ud83c\uddf3","\ud83c\uddfa\u200b\ud83c\uddf3")&&!n(e,"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f","\ud83c\udff4\u200b\udb40\udc67\u200b\udb40\udc62\u200b\udb40\udc65\u200b\udb40\udc6e\u200b\udb40\udc67\u200b\udb40\udc7f");case"emoji":return!n(e,"\ud83d\udc26\u200d\u2b1b","\ud83d\udc26\u200b\u2b1b")}return!1}function f(e,t,n){var r="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?new OffscreenCanvas(300,150):i.createElement("canvas"),a=r.getContext("2d",{willReadFrequently:!0}),o=(a.textBaseline="top",a.font="600 32px Arial",{});return e.forEach(function(e){o[e]=t(a,e,n)}),o}function t(e){var t=i.createElement("script");t.src=e,t.defer=!0,i.head.appendChild(t)}"undefined"!=typeof Promise&&(o="wpEmojiSettingsSupports",s=["flag","emoji"],n.supports={everything:!0,everythingExceptFlag:!0},e=new Promise(function(e){i.addEventListener("DOMContentLoaded",e,{once:!0})}),new Promise(function(t){var n=function(){try{var e=JSON.parse(sessionStorage.getItem(o));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf()<e.timestamp+604800&&"object"==typeof e.supportTests)return e.supportTests}catch(e){}return null}();if(!n){if("undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas&&"undefined"!=typeof URL&&URL.createObjectURL&&"undefined"!=typeof Blob)try{var e="postMessage("+f.toString()+"("+[JSON.stringify(s),u.toString(),p.toString()].join(",")+"));",r=new Blob([e],{type:"text/javascript"}),a=new Worker(URL.createObjectURL(r),{name:"wpTestEmojiSupports"});return void(a.onmessage=function(e){c(n=e.data),a.terminate(),t(n)})}catch(e){}c(n=f(s,u,p))}t(n)}).then(function(e){for(var t in e)n.supports[t]=e[t],n.supports.everything=n.supports.everything&&n.supports[t],"flag"!==t&&(n.supports.everythingExceptFlag=n.supports.everythingExceptFlag&&n.supports[t]);n.supports.everythingExceptFlag=n.supports.everythingExceptFlag&&!n.supports.flag,n.DOMReady=!1,n.readyCallback=function(){n.DOMReady=!0}}).then(function(){return e}).then(function(){var e;n.supports.everything||(n.readyCallback(),(e=n.source||{}).concatemoji?t(e.concatemoji):e.wpemoji&&e.twemoji&&(t(e.twemoji),t(e.wpemoji)))}))}((window,document),window._wpemojiSettings); /* ]]> */ </script> <link crossorigin='anonymous' rel='stylesheet' id='all-css-0-1' href='https://s2.wp.com/wp-content/mu-plugins/jetpack-plugin/sun/modules/infinite-scroll/infinity.css?m=1685115060i&cssminify=yes' type='text/css' media='all' /> <style id='wp-emoji-styles-inline-css'> img.wp-smiley, img.emoji { display: inline !important; border: none !important; box-shadow: none !important; height: 1em !important; width: 1em !important; margin: 0 0.07em !important; vertical-align: -0.1em !important; background: none !important; padding: 0 !important; } </style> <link crossorigin='anonymous' rel='stylesheet' id='all-css-2-1' href='https://s1.wp.com/_static/??-eJyljkEKwyAQRS9UMxoCWZWeRc1gTY3KzNjg7Zt2U+gq0OXn8R4f9qp8yYJZoKYWYmYI7ZgOKRyEEJ6jHvQwgmsxLeBS8Q+VoiNLHVh6wsEzX+C/kNxxOxP6WAwrSrVv3fbSRAWKy+kvPwmyEnPgr37brmaetNaTMfP6AnHzajo=&cssminify=yes' type='text/css' media='all' /> <style id='wp-block-library-inline-css'> .has-text-align-justify { text-align:justify; } .has-text-align-justify{text-align:justify;} </style> <link crossorigin='anonymous' rel='stylesheet' id='all-css-4-1' href='https://s2.wp.com/_static/??-eJzTLy/QzcxLzilNSS3WzyrWz01NyUxMzUnNTc0rQeEU5CRWphbp5qSmJyZX6uVm5uklFxfr6OPTDpRD5sM02efaGpoZmFkYGRuZGmQBAHPvL0Y=&cssminify=yes' type='text/css' media='all' /> <style id='jetpack-sharing-buttons-style-inline-css'> .jetpack-sharing-buttons__services-list{display:flex;flex-direction:row;flex-wrap:wrap;gap:0;list-style-type:none;margin:5px;padding:0}.jetpack-sharing-buttons__services-list.has-small-icon-size{font-size:12px}.jetpack-sharing-buttons__services-list.has-normal-icon-size{font-size:16px}.jetpack-sharing-buttons__services-list.has-large-icon-size{font-size:24px}.jetpack-sharing-buttons__services-list.has-huge-icon-size{font-size:36px}@media print{.jetpack-sharing-buttons__services-list{display:none!important}}.editor-styles-wrapper .wp-block-jetpack-sharing-buttons{gap:0;padding-inline-start:0}ul.jetpack-sharing-buttons__services-list.has-background{padding:1.25em 2.375em} </style> <link crossorigin='anonymous' rel='stylesheet' id='all-css-6-1' href='https://s2.wp.com/wp-content/plugins/coblocks/2.18.1-simple-rev.4/dist/coblocks-style.css?m=1681832297i&cssminify=yes' type='text/css' media='all' /> <style id='classic-theme-styles-inline-css'> /*! This file is auto-generated */ .wp-block-button__link{color:#fff;background-color:#32373c;border-radius:9999px;box-shadow:none;text-decoration:none;padding:calc(.667em + 2px) calc(1.333em + 2px);font-size:1.125em}.wp-block-file__button{background:#32373c;color:#fff;text-decoration:none} </style> <link crossorigin='anonymous' rel='stylesheet' id='all-css-8-1' href='https://s1.wp.com/_static/??/wp-content/mu-plugins/core-compat/wp-mediaelement.css,/wp-content/mu-plugins/wpcom-bbpress-premium-themes.css?m=1432920480j&cssminify=yes' type='text/css' media='all' /> <style id='global-styles-inline-css'> :root{--wp--preset--aspect-ratio--square: 1;--wp--preset--aspect-ratio--4-3: 4/3;--wp--preset--aspect-ratio--3-4: 3/4;--wp--preset--aspect-ratio--3-2: 3/2;--wp--preset--aspect-ratio--2-3: 2/3;--wp--preset--aspect-ratio--16-9: 16/9;--wp--preset--aspect-ratio--9-16: 9/16;--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #fff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--color--medium-blue: #0087be;--wp--preset--color--bright-blue: #00aadc;--wp--preset--color--dark-gray: #4d4d4b;--wp--preset--color--light-gray: #b3b3b1;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 36px;--wp--preset--font-size--x-large: 42px;--wp--preset--font-family--albert-sans: 'Albert Sans', sans-serif;--wp--preset--font-family--alegreya: Alegreya, serif;--wp--preset--font-family--arvo: Arvo, serif;--wp--preset--font-family--bodoni-moda: 'Bodoni Moda', serif;--wp--preset--font-family--bricolage-grotesque: 'Bricolage Grotesque', sans-serif;--wp--preset--font-family--cabin: Cabin, sans-serif;--wp--preset--font-family--chivo: Chivo, sans-serif;--wp--preset--font-family--commissioner: Commissioner, sans-serif;--wp--preset--font-family--cormorant: Cormorant, serif;--wp--preset--font-family--courier-prime: 'Courier Prime', monospace;--wp--preset--font-family--crimson-pro: 'Crimson Pro', serif;--wp--preset--font-family--dm-mono: 'DM Mono', monospace;--wp--preset--font-family--dm-sans: 'DM Sans', sans-serif;--wp--preset--font-family--dm-serif-display: 'DM Serif Display', serif;--wp--preset--font-family--domine: Domine, serif;--wp--preset--font-family--eb-garamond: 'EB Garamond', serif;--wp--preset--font-family--epilogue: Epilogue, sans-serif;--wp--preset--font-family--fahkwang: Fahkwang, sans-serif;--wp--preset--font-family--figtree: Figtree, sans-serif;--wp--preset--font-family--fira-sans: 'Fira Sans', sans-serif;--wp--preset--font-family--fjalla-one: 'Fjalla One', sans-serif;--wp--preset--font-family--fraunces: Fraunces, serif;--wp--preset--font-family--gabarito: Gabarito, system-ui;--wp--preset--font-family--ibm-plex-mono: 'IBM Plex Mono', monospace;--wp--preset--font-family--ibm-plex-sans: 'IBM Plex Sans', sans-serif;--wp--preset--font-family--ibarra-real-nova: 'Ibarra Real Nova', serif;--wp--preset--font-family--instrument-serif: 'Instrument Serif', serif;--wp--preset--font-family--inter: Inter, sans-serif;--wp--preset--font-family--josefin-sans: 'Josefin Sans', sans-serif;--wp--preset--font-family--jost: Jost, sans-serif;--wp--preset--font-family--libre-baskerville: 'Libre Baskerville', serif;--wp--preset--font-family--libre-franklin: 'Libre Franklin', sans-serif;--wp--preset--font-family--literata: Literata, serif;--wp--preset--font-family--lora: Lora, serif;--wp--preset--font-family--merriweather: Merriweather, serif;--wp--preset--font-family--montserrat: Montserrat, sans-serif;--wp--preset--font-family--newsreader: Newsreader, serif;--wp--preset--font-family--noto-sans-mono: 'Noto Sans Mono', sans-serif;--wp--preset--font-family--nunito: Nunito, sans-serif;--wp--preset--font-family--open-sans: 'Open Sans', sans-serif;--wp--preset--font-family--overpass: Overpass, sans-serif;--wp--preset--font-family--pt-serif: 'PT Serif', serif;--wp--preset--font-family--petrona: Petrona, serif;--wp--preset--font-family--piazzolla: Piazzolla, serif;--wp--preset--font-family--playfair-display: 'Playfair Display', serif;--wp--preset--font-family--plus-jakarta-sans: 'Plus Jakarta Sans', sans-serif;--wp--preset--font-family--poppins: Poppins, sans-serif;--wp--preset--font-family--raleway: Raleway, sans-serif;--wp--preset--font-family--roboto: Roboto, sans-serif;--wp--preset--font-family--roboto-slab: 'Roboto Slab', serif;--wp--preset--font-family--rubik: Rubik, sans-serif;--wp--preset--font-family--rufina: Rufina, serif;--wp--preset--font-family--sora: Sora, sans-serif;--wp--preset--font-family--source-sans-3: 'Source Sans 3', sans-serif;--wp--preset--font-family--source-serif-4: 'Source Serif 4', serif;--wp--preset--font-family--space-mono: 'Space Mono', monospace;--wp--preset--font-family--syne: Syne, sans-serif;--wp--preset--font-family--texturina: Texturina, serif;--wp--preset--font-family--urbanist: Urbanist, sans-serif;--wp--preset--font-family--work-sans: 'Work Sans', sans-serif;--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.67rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: 1.5rem;--wp--preset--spacing--60: 2.25rem;--wp--preset--spacing--70: 3.38rem;--wp--preset--spacing--80: 5.06rem;--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1);--wp--preset--shadow--crisp: 6px 6px 0px rgba(0, 0, 0, 1);}:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;}.has-albert-sans-font-family{font-family: var(--wp--preset--font-family--albert-sans) !important;}.has-alegreya-font-family{font-family: var(--wp--preset--font-family--alegreya) !important;}.has-arvo-font-family{font-family: var(--wp--preset--font-family--arvo) !important;}.has-bodoni-moda-font-family{font-family: var(--wp--preset--font-family--bodoni-moda) !important;}.has-bricolage-grotesque-font-family{font-family: var(--wp--preset--font-family--bricolage-grotesque) !important;}.has-cabin-font-family{font-family: var(--wp--preset--font-family--cabin) !important;}.has-chivo-font-family{font-family: var(--wp--preset--font-family--chivo) !important;}.has-commissioner-font-family{font-family: var(--wp--preset--font-family--commissioner) !important;}.has-cormorant-font-family{font-family: var(--wp--preset--font-family--cormorant) !important;}.has-courier-prime-font-family{font-family: var(--wp--preset--font-family--courier-prime) !important;}.has-crimson-pro-font-family{font-family: var(--wp--preset--font-family--crimson-pro) !important;}.has-dm-mono-font-family{font-family: var(--wp--preset--font-family--dm-mono) !important;}.has-dm-sans-font-family{font-family: var(--wp--preset--font-family--dm-sans) !important;}.has-dm-serif-display-font-family{font-family: var(--wp--preset--font-family--dm-serif-display) !important;}.has-domine-font-family{font-family: var(--wp--preset--font-family--domine) !important;}.has-eb-garamond-font-family{font-family: var(--wp--preset--font-family--eb-garamond) !important;}.has-epilogue-font-family{font-family: var(--wp--preset--font-family--epilogue) !important;}.has-fahkwang-font-family{font-family: var(--wp--preset--font-family--fahkwang) !important;}.has-figtree-font-family{font-family: var(--wp--preset--font-family--figtree) !important;}.has-fira-sans-font-family{font-family: var(--wp--preset--font-family--fira-sans) !important;}.has-fjalla-one-font-family{font-family: var(--wp--preset--font-family--fjalla-one) !important;}.has-fraunces-font-family{font-family: var(--wp--preset--font-family--fraunces) !important;}.has-gabarito-font-family{font-family: var(--wp--preset--font-family--gabarito) !important;}.has-ibm-plex-mono-font-family{font-family: var(--wp--preset--font-family--ibm-plex-mono) !important;}.has-ibm-plex-sans-font-family{font-family: var(--wp--preset--font-family--ibm-plex-sans) !important;}.has-ibarra-real-nova-font-family{font-family: var(--wp--preset--font-family--ibarra-real-nova) !important;}.has-instrument-serif-font-family{font-family: var(--wp--preset--font-family--instrument-serif) !important;}.has-inter-font-family{font-family: var(--wp--preset--font-family--inter) !important;}.has-josefin-sans-font-family{font-family: var(--wp--preset--font-family--josefin-sans) !important;}.has-jost-font-family{font-family: var(--wp--preset--font-family--jost) !important;}.has-libre-baskerville-font-family{font-family: var(--wp--preset--font-family--libre-baskerville) !important;}.has-libre-franklin-font-family{font-family: var(--wp--preset--font-family--libre-franklin) !important;}.has-literata-font-family{font-family: var(--wp--preset--font-family--literata) !important;}.has-lora-font-family{font-family: var(--wp--preset--font-family--lora) !important;}.has-merriweather-font-family{font-family: var(--wp--preset--font-family--merriweather) !important;}.has-montserrat-font-family{font-family: var(--wp--preset--font-family--montserrat) !important;}.has-newsreader-font-family{font-family: var(--wp--preset--font-family--newsreader) !important;}.has-noto-sans-mono-font-family{font-family: var(--wp--preset--font-family--noto-sans-mono) !important;}.has-nunito-font-family{font-family: var(--wp--preset--font-family--nunito) !important;}.has-open-sans-font-family{font-family: var(--wp--preset--font-family--open-sans) !important;}.has-overpass-font-family{font-family: var(--wp--preset--font-family--overpass) !important;}.has-pt-serif-font-family{font-family: var(--wp--preset--font-family--pt-serif) !important;}.has-petrona-font-family{font-family: var(--wp--preset--font-family--petrona) !important;}.has-piazzolla-font-family{font-family: var(--wp--preset--font-family--piazzolla) !important;}.has-playfair-display-font-family{font-family: var(--wp--preset--font-family--playfair-display) !important;}.has-plus-jakarta-sans-font-family{font-family: var(--wp--preset--font-family--plus-jakarta-sans) !important;}.has-poppins-font-family{font-family: var(--wp--preset--font-family--poppins) !important;}.has-raleway-font-family{font-family: var(--wp--preset--font-family--raleway) !important;}.has-roboto-font-family{font-family: var(--wp--preset--font-family--roboto) !important;}.has-roboto-slab-font-family{font-family: var(--wp--preset--font-family--roboto-slab) !important;}.has-rubik-font-family{font-family: var(--wp--preset--font-family--rubik) !important;}.has-rufina-font-family{font-family: var(--wp--preset--font-family--rufina) !important;}.has-sora-font-family{font-family: var(--wp--preset--font-family--sora) !important;}.has-source-sans-3-font-family{font-family: var(--wp--preset--font-family--source-sans-3) !important;}.has-source-serif-4-font-family{font-family: var(--wp--preset--font-family--source-serif-4) !important;}.has-space-mono-font-family{font-family: var(--wp--preset--font-family--space-mono) !important;}.has-syne-font-family{font-family: var(--wp--preset--font-family--syne) !important;}.has-texturina-font-family{font-family: var(--wp--preset--font-family--texturina) !important;}.has-urbanist-font-family{font-family: var(--wp--preset--font-family--urbanist) !important;}.has-work-sans-font-family{font-family: var(--wp--preset--font-family--work-sans) !important;} :where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;} :root :where(.wp-block-pullquote){font-size: 1.5em;line-height: 1.6;} :where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;} </style> <link crossorigin='anonymous' rel='stylesheet' id='all-css-10-1' href='https://s0.wp.com/_static/??-eJydj70OgzAMhF+oqfsDZar6KFUxFgQSx8KOUN++AXXo0InldDd8dzpYxGFiIzaI2UnIvWeFkUxeOH0zaGZ4ekboiWn2BdD/9oiqB/jptIEiKUhuwXNHQkXYXMnB60Czu4DaO9AesCDQhoTTrtn1zjbtFsEU14pHvJ+ba3Or6lNdjR/JRGmL&cssminify=yes' type='text/css' media='all' /> <style id='independent-publisher-2-style-inline-css'> .cat-links, .post-tags, .tags-links { clip: rect(1px, 1px, 1px, 1px); height: 1px; position: absolute; overflow: hidden; width: 1px; } </style> <style id='akismet-widget-style-inline-css'> .a-stats { --akismet-color-mid-green: #357b49; --akismet-color-white: #fff; --akismet-color-light-grey: #f6f7f7; max-width: 350px; width: auto; } .a-stats * { all: unset; box-sizing: border-box; } .a-stats strong { font-weight: 600; } .a-stats a.a-stats__link, .a-stats a.a-stats__link:visited, .a-stats a.a-stats__link:active { background: var(--akismet-color-mid-green); border: none; box-shadow: none; border-radius: 8px; color: var(--akismet-color-white); cursor: pointer; display: block; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen-Sans', 'Ubuntu', 'Cantarell', 'Helvetica Neue', sans-serif; font-weight: 500; padding: 12px; text-align: center; text-decoration: none; transition: all 0.2s ease; } /* Extra specificity to deal with TwentyTwentyOne focus style */ .widget .a-stats a.a-stats__link:focus { background: var(--akismet-color-mid-green); color: var(--akismet-color-white); text-decoration: none; } .a-stats a.a-stats__link:hover { filter: brightness(110%); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06), 0 0 2px rgba(0, 0, 0, 0.16); } .a-stats .count { color: var(--akismet-color-white); display: block; font-size: 1.5em; line-height: 1.4; padding: 0 13px; white-space: nowrap; } </style> <link crossorigin='anonymous' rel='stylesheet' id='all-css-12-1' href='https://s1.wp.com/_static/??-eJzTLy/QTc7PK0nNK9HPLdUtyClNz8wr1i9KTcrJTwcy0/WTi5G5ekCujj52Temp+bo5+cmJJZn5eSgc3bScxMwikFb7XFtDE1NLExMLc0OTLACohS2q&cssminify=yes' type='text/css' media='all' /> <link crossorigin='anonymous' rel='stylesheet' id='print-css-13-1' href='https://s1.wp.com/wp-content/mu-plugins/global-print/global-print.css?m=1465851035i&cssminify=yes' type='text/css' media='print' /> <style id='jetpack-global-styles-frontend-style-inline-css'> :root { --font-headings: unset; --font-base: unset; --font-headings-default: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; --font-base-default: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;} </style> <link crossorigin='anonymous' rel='stylesheet' id='all-css-16-1' href='https://s2.wp.com/wp-content/themes/h4/global.css?m=1420737423i&cssminify=yes' type='text/css' media='all' /> <script type="text/javascript" id="wpcom-actionbar-placeholder-js-extra"> /* <![CDATA[ */ var actionbardata = {"siteID":"3379246","postID":"0","siteURL":"https:\/\/herbsutter.com","xhrURL":"https:\/\/herbsutter.com\/wp-admin\/admin-ajax.php","nonce":"84c37fd87b","isLoggedIn":"","statusMessage":"","subsEmailDefault":"instantly","proxyScriptUrl":"https:\/\/s0.wp.com\/wp-content\/js\/wpcom-proxy-request.js?ver=20211021","i18n":{"followedText":"New posts from this site will now appear in your <a href=\"https:\/\/wordpress.com\/reader\">Reader<\/a>","foldBar":"Collapse this bar","unfoldBar":"Expand this bar","shortLinkCopied":"Shortlink copied to clipboard."}}; /* ]]> */ </script> <script type="text/javascript" id="jetpack-mu-wpcom-settings-js-before"> /* <![CDATA[ */ var JETPACK_MU_WPCOM_SETTINGS = {"assetsUrl":"https:\/\/s1.wp.com\/wp-content\/mu-plugins\/jetpack-mu-wpcom-plugin\/sun\/jetpack_vendor\/automattic\/jetpack-mu-wpcom\/src\/build\/"}; /* ]]> */ </script> <script crossorigin='anonymous' type='text/javascript' src='https://s2.wp.com/_static/??-eJzTLy/QzcxLzilNSS3WzwKiwtLUokoopZebmaeXVayjj0+Rbm5melFiSSqy4uT8vJLUvBJMA8sLkvNzdQuK8isqdYtSgWLFJVj0FOWUQNQA5exzbQ3NjQxMjQ3MLCyzAMS4QKo='></script> <script type="text/javascript" id="rlt-proxy-js-after"> /* <![CDATA[ */ rltInitialize( {"token":null,"iframeOrigins":["https:\/\/widgets.wp.com"]} ); /* ]]> */ </script> <link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://herbsutter.wordpress.com/xmlrpc.php?rsd" /> <meta name="generator" content="WordPress.com" /> <!-- Jetpack Open Graph Tags --> <meta property="og:type" content="website" /> <meta property="og:title" content="May 2013 &#8211; Sutter’s Mill" /> <meta property="og:site_name" content="Sutter’s Mill" /> <meta property="og:image" content="https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=200&#038;ts=1740535026" /> <meta property="og:image:width" content="200" /> <meta property="og:image:height" content="200" /> <meta property="og:image:alt" content="" /> <meta property="og:locale" content="en_US" /> <!-- End Jetpack Open Graph Tags --> <link rel="shortcut icon" type="image/x-icon" href="https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=32" sizes="16x16" /> <link rel="icon" type="image/x-icon" href="https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=32" sizes="16x16" /> <link rel="apple-touch-icon" href="https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=114" /> <link rel='openid.server' href='https://herbsutter.com/?openidserver=1' /> <link rel='openid.delegate' href='https://herbsutter.com/' /> <link rel="search" type="application/opensearchdescription+xml" href="https://herbsutter.com/osd.xml" title="Sutter’s Mill" /> <link rel="search" type="application/opensearchdescription+xml" href="https://s1.wp.com/opensearch.xml" title="WordPress.com" /> <style type="text/css"> .recentcomments a { display: inline !important; padding: 0 !important; margin: 0 !important; } table.recentcommentsavatartop img.avatar, table.recentcommentsavatarend img.avatar { border: 0px; margin: 0; } table.recentcommentsavatartop a, table.recentcommentsavatarend a { border: 0px !important; background-color: transparent !important; } td.recentcommentsavatarend, td.recentcommentsavatartop { padding: 0px 0px 1px 0px; margin: 0px; } td.recentcommentstextend { border: none !important; padding: 0px 0px 2px 10px; } .rtl td.recentcommentstextend { padding: 0px 10px 2px 0px; } td.recentcommentstexttop { border: none; padding: 0px 0px 0px 10px; } .rtl td.recentcommentstexttop { padding: 0px 10px 0px 0px; } </style> <meta name="description" content="10 posts published by Herb Sutter during May 2013" /> </head> <body class="archive date wp-embed-responsive customizer-styles-applied has-sidebar jetpack-reblog-enabled categories-hidden tags-hidden"> <div id="page" class="hfeed site"> <a class="skip-link screen-reader-text" href="#content">Skip to content</a> <div id="hero-header" class="site-hero-section"> <header id="masthead" class="site-header" role="banner"> <div class="inner"> <div class="site-branding"> <a class="site-logo-link" href="https://herbsutter.com/"> <img alt='' src='https://0.gravatar.com/avatar/928f5830f12d8977791539452bfc25c92912322476f0725253697ee1c45ce036?s=80&#038;d=identicon&#038;r=G' srcset='https://0.gravatar.com/avatar/928f5830f12d8977791539452bfc25c92912322476f0725253697ee1c45ce036?s=80&#038;d=identicon&#038;r=G 1x, https://0.gravatar.com/avatar/928f5830f12d8977791539452bfc25c92912322476f0725253697ee1c45ce036?s=120&#038;d=identicon&#038;r=G 1.5x, https://0.gravatar.com/avatar/928f5830f12d8977791539452bfc25c92912322476f0725253697ee1c45ce036?s=160&#038;d=identicon&#038;r=G 2x, https://0.gravatar.com/avatar/928f5830f12d8977791539452bfc25c92912322476f0725253697ee1c45ce036?s=240&#038;d=identicon&#038;r=G 3x, https://0.gravatar.com/avatar/928f5830f12d8977791539452bfc25c92912322476f0725253697ee1c45ce036?s=320&#038;d=identicon&#038;r=G 4x' class='avatar avatar-80 site-logo-image' height='80' width='80' loading='eager' decoding='async' /> </a><!-- .site-logo-link --> <p class="site-title"><a href="https://herbsutter.com/" rel="home">Sutter’s Mill</a></p> <p class="site-description">Herb Sutter on software development</p> </div><!-- .site-branding --> </div><!-- .inner --> </header><!-- #masthead --> </div> <div id="content-wrapper" class="content-wrapper"> <div id="content" class="site-content"> <div id="primary" class="content-area"> <main id="main" class="site-main" role="main"> <header class="page-header"> <h1 class="page-title">Month: <span>May 2013</span></h1> </header><!-- .page-header --> <article id="post-2070" class="post-2070 post type-post status-publish format-standard hentry category-c"> <header class="entry-header"> <h1 class="entry-title"><a href="https://herbsutter.com/2013/05/30/gotw-91-smart-pointer-parameters/" rel="bookmark">GotW #91: Smart Pointer&nbsp;Parameters</a></h1> </header><!-- .entry-header --> <div class="entry-content"> <blockquote> <p><strong>NOTE:</strong> Last year, I posted three new GotWs numbered #103-105. I decided leaving a gap in the numbers wasn&#8217;t best after all, so I am renumbering them to #89-91 to continue the sequence. Here is the updated version of what was GotW #105. </p> </blockquote> <p>  </p> <p><span style="color:#5a5a5a;"><em>How should you prefer to pass smart pointers, and why?<br /> </em></span></p> <p>  </p> <h1>Problem<br /> </h1> <h2>JG Question<br /> </h2> <p>1. What are the <em>performance</em> implications of the following function declaration? Explain. </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>void f( shared_ptr&lt;widget&gt; ); </code></pre> </p> <h2>Guru Questions<br /> </h2> <p>2. What are the <em>correctness</em> implications of the function declaration in #1? Explain with clear examples. </p> <p>3. A colleague is writing a function <span style="color:#2e74b5;">f</span> that takes an existing object of type <span style="color:#2e74b5;">widget</span> as a required input-only parameter, and trying to decide among the following basic ways to take the parameter (omitting <span style="color:#2e74b5;">const</span>): </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>void f( widget* ); (a)<br />void f( widget&amp; ); (b)<br />void f( unique_ptr&lt;widget&gt; ); (c)<br />void f( unique_ptr&lt;widget&gt;&amp; ); (d)<br />void f( shared_ptr&lt;widget&gt; ); (e)<br />void f( shared_ptr&lt;widget&gt;&amp; ); (f) </code></pre> </p> <p>Under what circumstances is each appropriate? Explain your answer, including where <span style="color:#2e74b5;">const</span> should or should not be added anywhere in the parameter type. </p> <p>(There are other ways to pass the parameter, but we will consider only the ones shown above.)</p> </div><!-- .entry-content --> <footer class="entry-footer"> <div class="entry-meta"> <span class="byline"> <a href="https://herbsutter.com/author/herbsutter/" title="Posts by Herb Sutter" rel="author">Herb Sutter</a> </span> <span class="cat-links"> <a href="https://herbsutter.com/category/c/" rel="category tag">C++</a> </span><!-- .cat-links --> <span class="comments-link"><a href="https://herbsutter.com/2013/05/30/gotw-91-smart-pointer-parameters/#comments">14 Comments</a></span><!-- .comments-link --> <span class="published-on"> <a href="https://herbsutter.com/2013/05/30/gotw-91-smart-pointer-parameters/" rel="bookmark"><time class="entry-date published" datetime="2013-05-30T15:12:42-08:00">2013-05-30</time><time class="updated" datetime="2013-05-30T15:12:43-08:00">2013-05-30</time></a> </span> <span class="word-count">1 Minute</span> </div><!-- .entry-meta --> </footer><!-- .entry-footer --> </article><!-- #post-## --> <article id="post-2068" class="post-2068 post type-post status-publish format-standard hentry category-c"> <header class="entry-header"> <h1 class="entry-title"><a href="https://herbsutter.com/2013/05/30/gotw-90-solution-factories/" rel="bookmark">GotW #90 Solution:&nbsp;Factories</a></h1> </header><!-- .entry-header --> <div class="entry-content"> <blockquote> <p><strong>NOTE:</strong> Last year, I posted three new GotWs numbered #103-105. I decided leaving a gap in the numbers wasn&#8217;t best after all, so I am renumbering them to #89-91 to continue the sequence. Here is the updated version of what was GotW #104. </p> </blockquote> <p>  </p> <p><span style="color:#5a5a5a;"><em>What should factory functions return, and why?<br /> </em></span></p> <p>  </p> <h1>Problem<br /> </h1> <p>While spelunking through the code of a new project you recently joined, you find the following factory function declaration: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>widget* load_widget( widget::id desired ); </code></pre> </p> <h2>JG Question<br /> </h2> <p>1. What&#8217;s wrong with this return type? </p> <h2>Guru Questions<br /> </h2> <p>2. Assuming that <span style="color:#2e74b5;">widget</span> is a polymorphic type, what is the recommended return type? Explain your answer, including any tradeoffs. </p> <p>3. You&#8217;d like to actually change the return type to match the recommendation in #2, but at first you worry about breaking source compatibility with existing calling code; recompiling existing callers is fine, but having to go change them all is not. Then you have an &#8220;aha!&#8221; moment, realizing that this is a fairly new project and all of your calling code is written using modern C++ idioms, and you go ahead and change the return type without fear, knowing it will require few or no code changes to callers. What makes you so confident? </p> <p>4. If <span style="color:#2e74b5;">widget</span> is not a polymorphic type, what is the recommended return type? Explain. </p> <p>  </p> <h1>Solution<br /> </h1> <h2>1. What&#8217;s wrong with this return type?<br /> </h2> <p>First, what can we know or reasonably expect from the two-line problem description? </p> <p>We&#8217;re told <span style="color:#2e74b5;">load_widget</span> is a factory function. It produces an object by &#8220;loading&#8221; it in some way and then returning it to the caller. Since the return type is a pointer, the result might be null. </p> <p>The caller will reasonably expect to use the object, whether by calling member functions on it or passing it to other functions or in some other way. That isn&#8217;t safe unless the caller owns the object to ensure it is alive—either the caller gets exclusive ownership, or it gets shared ownership if the factory also maintains an internal strong or weak reference. </p> <p>Because the caller has or shares ownership, he has to do something when the object is no longer needed. If the ownership is exclusive, he should destroy the object somehow. Otherwise, if the ownership is shared, he should decrement some shared reference count. </p> <p>Unfortunately, returning a <span style="color:#2e74b5;">widget*</span> has two major problems. First, it&#8217;s unsafe by default, because the default mode of operation (i.e., when the caller writes whitespace) is to leak a <span style="color:#2e74b5;">widget</span>: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// Example 1: Leak by default. Really, this is just so 20th-century...<br />// <br />widget* load_widget( widget::id desired );<br /><br />:::<br /><br />load_widget( some_id ); // oops </code></pre> </p> <p>The Example 1 code compiles cleanly, runs, and (un)happily leaks the <span style="color:#2e74b5;">widget</span>. </p> <blockquote> <p><strong>Guideline:</strong> Don&#8217;t use explicit <strong>new</strong>, <strong>delete</strong>, and owning <strong>*</strong> pointers, except in rare cases encapsulated inside the implementation of a low-level data structure. </p> </blockquote> <p>Second, the signature conveys absolutely no information other than &#8220;a <span style="color:#2e74b5;">widget</span>? sure, here you go! enjoy.&#8221; The documentation may state that (and how) the caller is to own the object, but the function declaration doesn&#8217;t—it&#8217;s either exclusive ownership or shared ownership, but which? Read and remember the function&#8217;s documentation, because the function declaration isn&#8217;t telling. The signature alone doesn&#8217;t even say whether the caller shares in ownership at all. </p> <h2>2. Assuming that widget is a polymorphic type, what is the recommended return type? Explain your answer, including any tradeoffs.<br /> </h2> <p>If <span style="color:#2e74b5;">widget</span> is a type that&#8217;s intended to be used polymorphically and held by pointer or reference, the factory should normally return a <span style="color:#2e74b5;">unique_ptr</span> to transfer ownership to the caller, or a <span style="color:#2e74b5;">shared_ptr</span> if the factory shares ownership by retaining a strong reference inside its internal data structures. </p> <blockquote> <p><strong>Guideline:</strong> A factory that produces a reference type should return a <strong>unique_ptr</strong> by default, or a <strong>shared_ptr</strong> if ownership is to be shared with the factory. </p> </blockquote> <p>This solves both problems: safety, and self-documentation. </p> <p>First, consider how this immediately solves the safety problem in Example 1: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// Example 2: Clean up by default. Much better...<br />// <br />unique_ptr&lt;widget&gt; load_widget( widget::id desired );<br /><br />:::<br /><br />load_widget( some_id ); // cleans up </code></pre> </p> <p>The Example 2 code compiles cleanly, runs, and happily cleans up the <span style="color:#2e74b5;">widget</span>. But it&#8217;s not just correct by default—it&#8217;s correct by construction, because there&#8217;s no way to make a mistake that results in a leak. </p> <p>Aside: Someone might say, &#8220;but can&#8217;t someone still write <span style="color:#2e74b5;">load_widget(some_id).release()</span>?&#8221; Of course they can, if they&#8217;re pathological; the correct answer is, &#8220;don&#8217;t do that.&#8221; Remember, our concern is to protect against Murphy, not Machiavelli—against bugs and mistakes, not deliberate crimes—and such pathological abuses fall into the latter category. That&#8217;s no different from, and doesn&#8217;t violate type safety any more than, explicitly calling <span style="color:#2e74b5;">Dispose</span> early in a C# <span style="color:#2e74b5;">using</span> block or explicitly calling <span style="color:#2e74b5;">close</span> early in a Java <span style="color:#2e74b5;">try</span>-with-resources block. </p> <p>What if the cleanup should be done by something other than a plain <span style="color:#2e74b5;">delete</span> call? Easy: Just use a custom deleter. The icing on the cake is that the factory itself knows which deleter is appropriate and can state it at the time it constructs the return value; the caller doesn&#8217;t need to worry about it, especially if he takes the result using an <span style="color:#2e74b5;">auto</span> variable. </p> <p>Second, this is self-documenting: A function that returns a <span style="color:#2e74b5;">unique_ptr</span> or a value clearly documents that it&#8217;s a pure &#8220;source&#8221; function, and one that returns a <span style="color:#2e74b5;">shared_ptr</span> clearly documents that it&#8217;s returning shared ownership and/or observation. </p> <p>Finally, why prefer <span style="color:#2e74b5;">unique_ptr</span> by default, if you don&#8217;t need to express shared ownership? Because it&#8217;s the Right Thing To Do for both performance and correctness, as noted in GotW #89, and leaves all options open to the caller: </p> <ul> <li>Returning <span style="color:#2e74b5;">unique_ptr</span> expresses returning unique ownership, which is the norm for a pure &#8220;source&#8221; factory function. </li> <li><span style="color:#2e74b5;">unique_ptr</span> can&#8217;t be beat in efficiency—moving one is about as cheap as moving/copying a raw pointer. </li> <li>If the caller wants to manage the produced object&#8217;s lifetime via <span style="color:#2e74b5;">shared_ptr</span>, they can easily convert to <span style="color:#2e74b5;">shared_ptr</span> via an implicit move operation—no need to say <span style="color:#2e74b5;">std::move</span> because the compiler already knows that the returned value is a temporary object. </li> <li>If the caller is using any other arbitrary method of maintaining the object&#8217;s lifetime, he can convert to a custom smart pointer or other lifetime management scheme simply by calling <span style="color:#2e74b5;">.release()</span>. This can be useful, and isn&#8217;t possible with <span style="color:#2e74b5;">shared_ptr</span>. </li> </ul> <p>Here it is in action: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// Example 2, continued<br />//<br /><br />// Accept as a unique_ptr (by default)<br />auto up = load_widget(1);<br /><br />// Accept as a shared_ptr (if desired)<br />auto sp = shared_ptr&lt;widget&gt;{ load_widget(2) };<br /><br />// Accept as your own smart pointer (if desired)<br />auto msp = my::smart_ptr&lt;widget&gt;{ load_widget(3).release() }; </code></pre> </p> <p>Of course, if the factory retains some shared ownership or observation, whether via an internal <span style="color:#2e74b5;">shared_ptr</span> or <span style="color:#2e74b5;">weak_ptr</span>, return <span style="color:#2e74b5;">shared_ptr</span>. The caller will be forced to continue using it as a <span style="color:#2e74b5;">shared_ptr</span>, but in that case that&#8217;s appropriate. </p> <h2>3. […] you go ahead and change the return type without fear, knowing it will require few or no code changes to callers. What makes you so confident?<br /> </h2> <p>Modern portable C++ code uses <span style="color:#2e74b5;">unique_ptr</span>, <span style="color:#2e74b5;">shared_ptr</span>, and <span style="color:#2e74b5;">auto</span>. Returning <span style="color:#2e74b5;">unique_ptr</span> works with all three; returning <span style="color:#2e74b5;">shared_ptr</span> works with the last two. </p> <p>If the caller accepts the return value in an <span style="color:#2e74b5;">auto</span> variables, such as <span style="color:#2e74b5;">auto w = load_widget(whatever);</span>, then the type will just naturally be correct, normal dereferencing will just work, and the only source ripple will be if the caller tries to explicitly <span style="color:#2e74b5;">delete</span> (if so, the <span style="color:#2e74b5;">delete</span> line can rather appropriately be deleted) or tries to store into a non-local object of a different type. </p> <blockquote> <p><strong>Guideline:</strong> Prefer declaring variables using <strong>auto</strong>. It&#8217;s shorter, and helps to insulate your code from needless source ripples due to minor type changes. </p> </blockquote> <p>Otherwise, if the caller isn&#8217;t using <span style="color:#2e74b5;">auto</span>, then it&#8217;s likely already using the result to initialize a <span style="color:#2e74b5;">unique_ptr</span> or <span style="color:#2e74b5;">shared_ptr</span> because modern C++ calling code does not traffick in raw pointers for non-parameter variables (more on this next time). In either case, returning a <span style="color:#2e74b5;">unique_ptr</span> just works: A <span style="color:#2e74b5;">unique_ptr</span> can be seamlessly moved into either of those types, and if the semantics are to return shared ownership and then the caller should already be using a <span style="color:#2e74b5;">shared_ptr</span> and things will again work just fine (only probably better than before, because for the original return by raw pointer to work correctly the return type was probably forced to jump through the <span style="color:#2e74b5;">enable_shared_from_this</span> hoop, which isn&#8217;t needed if we just return a <span style="color:#2e74b5;">shared_ptr</span> explicitly). </p> <h2>4. If widget is not a polymorphic type, what is the recommended return type? Explain.<br /> </h2> <p>If <span style="color:#2e74b5;">widget</span> is not a polymorphic type, which typically means it&#8217;s a copyable value type or a move-only type, the factory should return a <span style="color:#2e74b5;">widget</span> by value. But what kind of value? </p> <p>In C++98, programmers would often resort to returning a large object by pointer just to avoid the penalty of copying its state: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// Example 4(a): Obsolete convention: return a * just to avoid a copy <br />//<br />/*BAD*/ vector&lt;gadget&gt;* load_gadgets() {<br /> vector&lt;gadget&gt;* ret = new vector&lt;gadget&gt;();<br /> // ... populate *ret ...<br /> return ret;<br />}<br /><br />// Obsolete calling code (note: NOT exception-safe) <br />vector&lt;gadget&gt;* p = load_gadgets();<br />if(p) use(*p);<br />delete p; </code></pre> </p> <p>This has all of the usability and fragility problems discussed in #1. Today, normally we should just return by value, because we will incur only a cheap move operation, not a deep copy, to hand the result to the caller: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// Example 4(b): Default recommendation: return the value<br />//<br />vector&lt;gadget&gt; load_gadgets() {<br /> vector&lt;gadget&gt; ret;<br /> // ... populate ret ...<br /> return ret;<br />}<br /><br />// Calling code (exception-safe)<br />auto v = load_gadgets();<br />use(v); </code></pre> </p> <p>Most of the time, return movable objects by value. That&#8217;s all there is to it, if the only reason for the pointer on the return type was to avoid the copy. </p> <p>There could be one additional reason the function might have returned a pointer, namely to return <span style="color:#2e74b5;">nullptr</span> to indicate failure to produce an object. Normally it&#8217;s better throw an exception to report an error if we fail to load the <span style="color:#2e74b5;">widget</span>. However, if not being able to load the <span style="color:#2e74b5;">widget</span> is normal operation and should not be considered an error, return an <span style="color:#2e74b5;">optional&lt;widget&gt;</span>, and probably make the factory <span style="color:#2e74b5;">noexcept</span> if no other kinds of errors need to be reported than are communicated well by returning an empty <span style="color:#2e74b5;">optional&lt;widget&gt;</span>. </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// Example 4(c): Alternative if not returning an object is normal<br />//<br />optional&lt;vector&lt;gadget&gt;&gt; load_gadgets() noexcept {<br /> vector&lt;gadget&gt; ret;<br /> // ... populate ret ...<br /> if( success ) // return vector (might be empty)<br /> return move(ret); // note: move() here to avoid a silent copy<br /> else<br /> return {}; // not returning anything<br />}<br /><br />// Calling code (exception-safe)<br />auto v = load_gadgets();<br />if(v) use(*v); </code></pre> </p> <blockquote> <p><strong>Guideline:</strong> A factory that produces a non-reference type should return a value by default, and throw an exception if it fails to create the object. If not creating the object can be a normal result, return an <strong>optional&lt;&gt;</strong> value. </p> </blockquote> <h2>Coda<br /> </h2> <p>By the way, see that test for <span style="color:#2e74b5;">if(v)</span> in the last line of Example 4(c)? It calls a cool function of <span style="color:#2e74b5;">optional&lt;T&gt;</span>, namely <span style="color:#2e74b5;">operator bool</span>. What makes bool so cool? In part because of how many C++ features it exercises. Here is its declaration… just think of what this lets you safely do, including at compile time! Enjoy. </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>constexpr explicit optional&lt;T&gt;::operator bool() const noexcept; </code></pre> </p> <h2>Acknowledgments<br /> </h2> <p>Thanks in particular to the following for their feedback to improve this article: Johannes Schaub, Leo, Vincent Jacquet.</p> </div><!-- .entry-content --> <footer class="entry-footer"> <div class="entry-meta"> <span class="byline"> <a href="https://herbsutter.com/author/herbsutter/" title="Posts by Herb Sutter" rel="author">Herb Sutter</a> </span> <span class="cat-links"> <a href="https://herbsutter.com/category/c/" rel="category tag">C++</a> </span><!-- .cat-links --> <span class="comments-link"><a href="https://herbsutter.com/2013/05/30/gotw-90-solution-factories/#comments">29 Comments</a></span><!-- .comments-link --> <span class="published-on"> <a href="https://herbsutter.com/2013/05/30/gotw-90-solution-factories/" rel="bookmark"><time class="entry-date published" datetime="2013-05-30T15:04:45-08:00">2013-05-30</time><time class="updated" datetime="2013-06-04T09:31:37-08:00">2013-06-04</time></a> </span> <span class="word-count">8 Minutes</span> </div><!-- .entry-meta --> </footer><!-- .entry-footer --> </article><!-- #post-## --> <article id="post-2040" class="post-2040 post type-post status-publish format-standard hentry category-c"> <header class="entry-header"> <h1 class="entry-title"><a href="https://herbsutter.com/2013/05/29/gotw-90-factories/" rel="bookmark">GotW #90: Factories</a></h1> </header><!-- .entry-header --> <div class="entry-content"> <blockquote> <p><strong>NOTE:</strong> Last year, I posted three new GotWs numbered #103-105. I decided leaving a gap in the numbers wasn&#8217;t best after all, so I am renumbering them to #89-91 to continue the sequence. Here is the updated version of what was GotW #104. </p> </blockquote> <p>  </p> <p><span style="color:#5a5a5a;"><em>What should factory functions return, and why?<br /> </em></span></p> <p>  </p> <h1>Problem<br /> </h1> <p>While spelunking through the code of a new project you recently joined, you find the following factory function declaration: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>widget* load_widget( widget::id desired ); </code></pre> </p> <h2>JG Question<br /> </h2> <p>1. What&#8217;s wrong with this return type? </p> <h2>Guru Questions<br /> </h2> <p>2. Assuming that <span style="color:#2e74b5;">widget</span> is a polymorphic type, what is the recommended return type? Explain your answer, including any tradeoffs. </p> <p>3. You&#8217;d like to actually change the return type to match the recommendation in #2, but at first you worry about breaking source compatibility with existing calling code; recompiling existing callers is fine, but having to go change them all is not. Then you have an &#8220;aha!&#8221; moment, realizing that this is a fairly new project and all of your calling code is written using modern C++ idioms, and you go ahead and change the return type without fear, knowing it will require few or no code changes to callers. What makes you so confident? </p> <p>4. If <span style="color:#2e74b5;">widget</span> is not a polymorphic type, what is the recommended return type? Explain.</p> </div><!-- .entry-content --> <footer class="entry-footer"> <div class="entry-meta"> <span class="byline"> <a href="https://herbsutter.com/author/herbsutter/" title="Posts by Herb Sutter" rel="author">Herb Sutter</a> </span> <span class="cat-links"> <a href="https://herbsutter.com/category/c/" rel="category tag">C++</a> </span><!-- .cat-links --> <span class="comments-link"><a href="https://herbsutter.com/2013/05/29/gotw-90-factories/#comments">16 Comments</a></span><!-- .comments-link --> <span class="published-on"> <a href="https://herbsutter.com/2013/05/29/gotw-90-factories/" rel="bookmark"><time class="entry-date published updated" datetime="2013-05-29T10:54:21-08:00">2013-05-29</time></a> </span> <span class="word-count">1 Minute</span> </div><!-- .entry-meta --> </footer><!-- .entry-footer --> </article><!-- #post-## --> <article id="post-2035" class="post-2035 post type-post status-publish format-standard hentry category-c"> <header class="entry-header"> <h1 class="entry-title"><a href="https://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/" rel="bookmark">GotW #89 Solution: Smart&nbsp;Pointers</a></h1> </header><!-- .entry-header --> <div class="entry-content"> <blockquote> <p><strong>NOTE:</strong> Last year, I posted three new GotWs numbered #103-105. I decided leaving a gap in the numbers wasn&#8217;t best after all, so I am renumbering them to #89-91 to continue the sequence. Here is the updated version of what was GotW #103. </p> </blockquote> <p>  </p> <p><span style="color:#5a5a5a;"><em>There&#8217;s a lot to love about standard smart pointers in general, and unique_ptr in particular.<br /> </em></span></p> <p>  </p> <h1>Problem<br /> </h1> <h2>JG Question<br /> </h2> <p>1. When should you use <span style="color:#2e74b5;">shared_ptr</span> vs. <span style="color:#2e74b5;">unique_ptr</span>? List as many considerations as you can. </p> <h2>Guru Question<br /> </h2> <p>2. Why should you almost always use <span style="color:#2e74b5;">make_shared</span> to create an object to be owned by <span style="color:#2e74b5;">shared_ptr</span>s? Explain. </p> <p>3. Why should you almost always use <span style="color:#2e74b5;">make_unique</span> to create an object to be initially owned by a <span style="color:#2e74b5;">unique_ptr</span>? Explain. </p> <p>4. What&#8217;s the deal with <span style="color:#2e74b5;">auto_ptr</span>? </p> <p>  </p> <h1>Solution<br /> </h1> <h2>1. When should you use shared_ptr vs. unique_ptr?<br /> </h2> <p>When in doubt, prefer <span style="color:#2e74b5;">unique_ptr</span> by default, and you can always later move-convert to <span style="color:#2e74b5;">shared_ptr</span> if you need it. If you do know from the start you need shared ownership, however, go directly to <span style="color:#2e74b5;">shared_ptr</span> via <span style="color:#2e74b5;">make_shared</span> (see #2 below). </p> <p>There are three major reasons to say &#8220;when in doubt, prefer <span style="color:#2e74b5;">unique_ptr</span>.&#8221; </p> <p>First, use the simplest semantics that are sufficient<em>:</em> Choose the right smart pointer to most directly express your intent, and what you need (now). If you are creating a new object and don&#8217;t know that you&#8217;ll eventually need shared ownership, use <span style="color:#2e74b5;">unique_ptr</span> which expresses unique ownership. You can still put it in a container (e.g., <span style="color:#2e74b5;">vector&lt;unique_ptr&lt;widget&gt;&gt;</span>) and do most other things you want to do with a raw pointer, only safely. If you later need shared ownership, you can always move-convert the <span style="color:#2e74b5;">unique_ptr</span> to a <span style="color:#2e74b5;">shared_ptr</span>. </p> <p>Second, a <span style="color:#2e74b5;">unique_ptr</span> is more efficient than a <span style="color:#2e74b5;">shared_ptr</span>. A <span style="color:#2e74b5;">unique_ptr</span> doesn&#8217;t need to maintain reference count information and a control block under the covers, and is designed to be just about as cheap to move and use as a raw pointer. When you don&#8217;t ask for more than you need, you don&#8217;t incur overheads you won&#8217;t use. </p> <p>Third, starting with <span style="color:#2e74b5;">unique_ptr</span> is more flexible and keeps your options open. If you start with a <span style="color:#2e74b5;">unique_ptr</span>, you can always later convert to a <span style="color:#2e74b5;">shared_ptr</span> via move, or to another custom smart pointer (or even to a raw pointer) via <span style="color:#2e74b5;">.get()</span> or <span style="color:#2e74b5;">.release()</span>. </p> <blockquote> <p><strong>Guideline:</strong> Prefer to use the standard smart pointers, <strong>unique_ptr</strong> by default and <strong>shared_ptr</strong> if sharing is needed. They are the common types that all C++ libraries can understand. Use other smart pointer types only if necessary for interoperability with other libraries, or when necessary for custom behavior you can&#8217;t achieve with deleters and allocators on the standard pointers. </p> </blockquote> <h2>2. Why should you almost always use make_shared to create an object to be owned by shared_ptrs? Explain.<br /> </h2> <p>Note: If you need to create an object using a custom allocator, which is rare, you can use <span style="color:#2e74b5;">allocate_shared</span>. Note that even though its name is slightly different, <span style="color:#2e74b5;">allocate_shared</span> should be viewed as &#8220;just the flavor of <span style="color:#2e74b5;">make_shared</span> that lets you specify an allocator,&#8221; so I&#8217;m mainly going to talk about them both as <span style="color:#2e74b5;">make_shared</span> here and not distinguish much between them. </p> <p>There are two main cases where you can&#8217;t use <span style="color:#2e74b5;">make_shared</span> (or <span style="color:#2e74b5;">allocate_shared</span>) to create an object that you know will be owned by <span style="color:#2e74b5;">shared_ptr</span>s: (a) if you need a custom deleter, such as because of using <span style="color:#2e74b5;">shared_ptr</span>s to manage a non-memory resource or an object allocated in a nonstandard memory area, you can&#8217;t use <span style="color:#2e74b5;">make_shared</span> because it doesn&#8217;t support specifying a deleter; and (b) if you are adopting a raw pointer to an object being handed to you from other (usually legacy) code, you would construct a <span style="color:#2e74b5;">shared_ptr</span> from that raw pointer directly. </p> <blockquote> <p><strong>Guideline:</strong> Use <strong>make_shared</strong> (or, if you need a custom allocator, <strong>allocate_shared</strong>) to create an object you know will be owned by <strong>shared_ptr</strong>s, unless you need a custom deleter or are adopting a raw pointer from elsewhere. </p> </blockquote> <p>So, why use <span style="color:#2e74b5;">make_shared</span> (or, if you need a custom allocator, <span style="color:#2e74b5;">allocate_shared</span>) whenever you can, which is nearly always? There are two main reasons: simplicity, and efficiency. </p> <p>First, with <span style="color:#2e74b5;">make_shared</span> the code is simpler. Write for clarity and correctness first. </p> <p>Second, using <span style="color:#2e74b5;">make_shared</span> is more efficient. The <span style="color:#2e74b5;">shared_ptr</span> implementation has to maintain housekeeping information in a control block shared by all <span style="color:#2e74b5;">shared_ptr</span>s and <span style="color:#2e74b5;">weak_ptr</span>s referring to a given object. In particular, that housekeeping information has to include not just one but two reference counts: </p> <ul> <li>A &#8220;strong reference&#8221; count to track the number of <span style="color:#2e74b5;">shared_ptr</span>s currently keeping the object alive. The shared object is destroyed (and possibly deallocated) when the last strong reference goes away. </li> <li>A &#8220;weak reference&#8221; count to track the number of <span style="color:#2e74b5;">weak_ptr</span>s currently observing the object. The shared housekeeping control block is destroyed and deallocated (and the shared object is deallocated if it was not already) when the last weak reference goes away. </li> </ul> <p>If you allocate the object separately via a raw <span style="color:#2e74b5;">new</span> expression, then pass it to <span style="color:#2e74b5;">a shared_ptr</span>, the <span style="color:#2e74b5;">shared_ptr</span> implementation has no alternative but to allocate the control block separately, as shown in Example 2(a) and Figure 2(a). </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// Example 2(a): Separate allocation<br />auto sp1 = shared_ptr&lt;widget&gt;{ new widget{} };<br />auto sp2 = sp1; </code></pre> </p> <p style="text-align:center;"><img src="https://herbsutter.com/wp-content/uploads/2013/05/053013_2139_gotw89solut1.png?w=1100" alt="" /> </p> <p style="text-align:center;">Figure 2(a): Approximate memory layout for Example 2(a). </p> <p>We&#8217;d like to avoid doing two separate allocations here. If you use <span style="color:#2e74b5;">make_shared</span> to allocate the object and the <span style="color:#2e74b5;">shared_ptr</span> all in one go, then the implementation can fold them together in a single allocation, as shown in Example 2(b) and Figure 2(b). </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// Example 2(b): Single allocation<br />auto sp1 = make_shared&lt;widget&gt;();<br />auto sp2 = sp1; </code></pre> </p> <p style="text-align:center;"><img src="https://herbsutter.com/wp-content/uploads/2013/05/053013_2139_gotw89solut2.png?w=1100" alt="" /> </p> <p style="text-align:center;">Figure 2(b): Approximate memory layout for Example 2(b). </p> <p>Note that combining the allocations has two major advantages: </p> <ul> <li>It reduces allocation overhead, including memory fragmentation. First, the most obvious way it does this is by reducing the number of allocation requests, which are typically more expensive operations. This also helps reduce contention on allocators (some allocators don&#8217;t scale well). Second, using only one chunk of memory instead of two reduces the per-allocation overhead. Whenever you ask for a chunk of memory, the system must give you at least that many bytes, and often gives you a few more because of using fixed-size pools or tacking on housekeeping information per allocation. So by using a single chunk of memory, we tend to reduce the total extra overhead. Finally, we also naturally reduce the number of &#8220;dead&#8221; extra in-between gaps that cause fragmentation. </li> <li>It improves locality. The reference counts are frequently used with the object, and for small objects are likely to be on the same cache line, which improves cache performance (as long as there isn&#8217;t some thread copying the smart pointer in a tight loop; don&#8217;t do that). </li> </ul> <p>As always, when you can express more of what you&#8217;re trying to achieve as a single function call, you&#8217;re giving the system a better chance to figure out a way to do the job more efficiently. This is just as true when inserting 100 elements into a <span style="color:#2e74b5;">vector</span> using a single range-insert call to <span style="color:#2e74b5;">v.insert( first, last )</span> instead of 100 calls to <span style="color:#2e74b5;">v.insert( value )</span> as it is when using a single call to <span style="color:#2e74b5;">make_shared</span> instead of separate calls to <span style="color:#2e74b5;">new widget()</span> and <span style="color:#2e74b5;">shared_ptr( widget* )</span>. </p> <p>There are two more advantages: Using <span style="color:#2e74b5;">make_shared</span> avoids explicit <span style="color:#2e74b5;">new</span> and avoids an exception safety issue. Both of these also apply to <span style="color:#2e74b5;">make_unique</span>, so we&#8217;ll cover them under #3. </p> <h2>3. Why should you almost always use make_unique to create an object to be initially owned by a unique_ptr? Explain.<br /> </h2> <p>As with <span style="color:#2e74b5;">make_shared</span>, there are two main cases where you can&#8217;t use <span style="color:#2e74b5;">make_unique</span> to create an object that you know will be owned (at least initially) by a <span style="color:#2e74b5;">unique_ptr</span>: if you need a custom deleter, or if you are adopting a raw pointer. </p> <p>Otherwise, which is nearly always, prefer <span style="color:#2e74b5;">make_unique</span>. </p> <blockquote> <p><strong>Guideline:</strong> Use <strong>make_unique</strong> to create an object that isn&#8217;t shared (at least not yet), unless you need a custom deleter or are adopting a raw pointer from elsewhere. </p> </blockquote> <p>Besides symmetry with <span style="color:#2e74b5;">make_shared</span>, <span style="color:#2e74b5;">make_unique</span> offers at least two other advantages. First, you should prefer use <span style="color:#2e74b5;">make_unique&lt;T&gt;()</span> instead of the more-verbose <span style="color:#2e74b5;">unique_ptr&lt;T&gt;{ new T{} }</span> because you should avoid explicit <span style="color:#2e74b5;">new</span> in general: </p> <blockquote> <p><strong>Guideline:</strong> Don&#8217;t use explicit <strong>new</strong>, <strong>delete</strong>, and owning <strong>*</strong> pointers, except in rare cases encapsulated inside the implementation of a low-level data structure. </p> </blockquote> <p>Second, it avoids some known exception safety issues with naked <span style="color:#2e74b5;">new</span>. Here&#8217;s an example: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>void sink( unique_ptr&lt;widget&gt;, unique_ptr&lt;gadget&gt; );<br /><br />sink( unique_ptr&lt;widget&gt;{new widget{}},<br /> unique_ptr&lt;gadget&gt;{new gadget{}} ); // Q1: do you see the problem? </code></pre> </p> <p>Briefly, if you allocate and construct the <span style="color:#2e74b5;">new widget</span> first, then get an exception while allocating or constructing the <span style="color:#2e74b5;">new gadget</span>, the <span style="color:#2e74b5;">widget</span> is leaked. You might think: &#8220;Well, I could just change <span style="color:#2e74b5;">new widget{}</span> to <span style="color:#2e74b5;">make_unique&lt;widget&gt;()</span> and this problem would go away, right?&#8221; To wit: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>sink( make_unique&lt;widget&gt;(),<br /> unique_ptr&lt;gadget&gt;{new gadget{}} ); // Q2: is this better? </code></pre> </p> <p>The answer is no, because C++ leaves the order of evaluation of function arguments unspecified and so either the <span style="color:#2e74b5;">new widget</span> or the <span style="color:#2e74b5;">new gadget</span> could be performed first. If the <span style="color:#2e74b5;">new gadget</span> is allocated and constructed first, then the <span style="color:#2e74b5;">make_unique&lt;widget&gt;</span> throws, we have the same problem. </p> <p>But while just changing one of the arguments to use <span style="color:#2e74b5;">make_unique</span> doesn&#8217;t close the hole, changing them both to <span style="color:#2e74b5;">make_unique</span> really does completely eliminate the problem: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>sink( make_unique&lt;widget&gt;(), make_unique&lt;gadget&gt;() ); // exception-safe </code></pre> </p> <p>This exception safety issue is covered in more detail in GotW #56. </p> <blockquote> <p><strong>Guideline:</strong> To allocate an object, prefer to write <strong>make_unique</strong> by default, and write <strong>make_shared</strong> when you know the object&#8217;s lifetime is going to be managed by using <strong>shared_ptr</strong>s. </p> </blockquote> <h2>4. What&#8217;s the deal with auto_ptr?<br /> </h2> <p><span style="color:#2e74b5;">auto_ptr</span> is most charitably characterized as a valiant attempt to create a <span style="color:#2e74b5;">unique_ptr</span> before C++ had move semantics. <span style="color:#2e74b5;">auto_ptr</span> is now deprecated, and should not be used in new code. </p> <p>If you have <span style="color:#2e74b5;">auto_ptr</span> in an existing code base, when you get a chance try doing a global search-and-replace of <span style="color:#2e74b5;">auto_ptr</span> to <span style="color:#2e74b5;">unique_ptr</span>; the vast majority of uses will work the same, and it might expose (as a compile-time error) or fix (silently) a bug or two you didn&#8217;t know you had. </p> <h2>Acknowledgments<br /> </h2> <p>Thanks in particular to the following for their feedback to improve this article: celeborn2bealive, Andy Prowl, Chris Vine, Marek.</p> </div><!-- .entry-content --> <footer class="entry-footer"> <div class="entry-meta"> <span class="byline"> <a href="https://herbsutter.com/author/herbsutter/" title="Posts by Herb Sutter" rel="author">Herb Sutter</a> </span> <span class="cat-links"> <a href="https://herbsutter.com/category/c/" rel="category tag">C++</a> </span><!-- .cat-links --> <span class="comments-link"><a href="https://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/#comments">53 Comments</a></span><!-- .comments-link --> <span class="published-on"> <a href="https://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/" rel="bookmark"><time class="entry-date published" datetime="2013-05-29T10:49:21-08:00">2013-05-29</time><time class="updated" datetime="2013-05-30T13:39:27-08:00">2013-05-30</time></a> </span> <span class="word-count">7 Minutes</span> </div><!-- .entry-meta --> </footer><!-- .entry-footer --> </article><!-- #post-## --> <article id="post-2025" class="post-2025 post type-post status-publish format-standard hentry category-c"> <header class="entry-header"> <h1 class="entry-title"><a href="https://herbsutter.com/2013/05/28/gotw-89-smart-pointers/" rel="bookmark">GotW #89: Smart&nbsp;Pointers</a></h1> </header><!-- .entry-header --> <div class="entry-content"> <blockquote> <p><strong>NOTE:</strong> Last year, I posted three new GotWs numbered #103-105. I decided leaving a gap in the numbers wasn&#8217;t best after all, so I am renumbering them to #89-91 to continue the sequence. Here is the updated version of what was GotW #103. </p> </blockquote> <p>  </p> <p><span style="color:#5a5a5a;"><em>There&#8217;s a lot to love about standard smart pointers in general, and unique_ptr in particular.<br /> </em></span></p> <p>  </p> <h1>Problem<br /> </h1> <h2>JG Question<br /> </h2> <p>1. When should you use <span style="color:#2e74b5;">shared_ptr</span> vs. <span style="color:#2e74b5;">unique_ptr</span>? List as many considerations as you can. </p> <h2>Guru Question<br /> </h2> <p>2. Why should you almost always use <span style="color:#2e74b5;">make_shared</span> to create an object to be owned by <span style="color:#2e74b5;">shared_ptr</span>s? Explain. </p> <p>3. Why should you almost always use <span style="color:#2e74b5;">make_unique</span> to create an object to be initially owned by a <span style="color:#2e74b5;">unique_ptr</span>? Explain. </p> <p>4. What&#8217;s the deal with <span style="color:#2e74b5;">auto_ptr</span>?</p> </div><!-- .entry-content --> <footer class="entry-footer"> <div class="entry-meta"> <span class="byline"> <a href="https://herbsutter.com/author/herbsutter/" title="Posts by Herb Sutter" rel="author">Herb Sutter</a> </span> <span class="cat-links"> <a href="https://herbsutter.com/category/c/" rel="category tag">C++</a> </span><!-- .cat-links --> <span class="comments-link"><a href="https://herbsutter.com/2013/05/28/gotw-89-smart-pointers/#comments">9 Comments</a></span><!-- .comments-link --> <span class="published-on"> <a href="https://herbsutter.com/2013/05/28/gotw-89-smart-pointers/" rel="bookmark"><time class="entry-date published" datetime="2013-05-28T16:08:38-08:00">2013-05-28</time><time class="updated" datetime="2013-05-30T13:10:24-08:00">2013-05-30</time></a> </span> <span class="word-count">1 Minute</span> </div><!-- .entry-meta --> </footer><!-- .entry-footer --> </article><!-- #post-## --> <article id="post-2023" class="post-2023 post type-post status-publish format-standard hentry category-c"> <header class="entry-header"> <h1 class="entry-title"><a href="https://herbsutter.com/2013/05/28/gotw-6b-solution-const-correctness-part-2/" rel="bookmark">GotW #6b Solution: Const-Correctness, Part&nbsp;2</a></h1> </header><!-- .entry-header --> <div class="entry-content"> <p><span style="color:#5a5a5a;"><em>const and mutable are powerful tools for writing safer code. Use them consistently.</em></span> </p> <h1>Problem<br /> </h1> <h2>Guru Question<br /> </h2> <p>In the following code, add or remove <span style="color:#2e74b5;">const</span> (including minor variants and related keywords) wherever appropriate. Note: Don&#8217;t comment on or change the structure of this program. It&#8217;s contrived and condensed for illustration only. </p> <p>For bonus points: In what places are the program&#8217;s results undefined or uncompilable due to <span style="color:#2e74b5;">const</span> errors? </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>class polygon {<br />public:<br /> polygon() : area{-1} {}<br /><br /> void add_point( const point pt ) { area = -1;<br /> points.push_back(pt); }<br /><br /> point get_point( const int i ) { return points[i]; }<br /><br /> int get_num_points() { return points.size(); }<br /><br /> double get_area() {<br /> if( area &lt; 0 ) // if not yet calculated and cached<br /> calc_area(); // calculate now<br /> return area;<br /> }<br /><br />private:<br /> void calc_area() {<br /> area = 0;<br /> vector&lt;point&gt;::iterator i;<br /> for( i = begin(points); i != end(points); ++i )<br /> area += /* some work using *i */;<br /> }<br /><br /> vector&lt;point&gt; points;<br /> double area;<br />};<br /><br />polygon operator+( polygon&amp; lhs, polygon&amp; rhs ) {<br /> auto ret = lhs;<br /> auto last = rhs.get_num_points();<br /> for( auto i = 0; i &lt; last; ++i ) // concatenate<br /> ret.add_point( rhs.get_point(i) );<br /> return ret;<br />}<br /><br />void f( const polygon&amp; poly ) {<br /> const_cast&lt;polygon&amp;&gt;(poly).add_point( {0,0} );<br />}<br /><br />void g( polygon&amp; const poly ) { poly.add_point( {1,1} ); }<br /><br />void h( polygon* const poly ) { poly-&gt;add_point( {2,2} ); }<br /><br />int main() {<br /> polygon poly;<br /> const polygon cpoly;<br /><br /> f(poly);<br /> f(cpoly);<br /> g(poly);<br /> h(&amp;poly);<br />} </code></pre> </p> <p>  </p> <h1>Solution<br /> </h1> <p>When I pose this kind of problem, I find that most people think the problem is on the easy side and address only the more-usual <span style="color:#2e74b5;">const</span> issues. There are, however, subtleties that are worth knowing, and hence this Item. </p> <h3>1. The point object is passed by value, so there is little benefit to declaring it const.<br /> </h3> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code> void add_point( const point pt )<span style="color:#2e74b5;"> </span></code></pre> </p> <p>In this particular case, because the function is defined inline, the <span style="color:#2e74b5;">const</span> value parameter can make sense. This is because for inline functions the declaration and definition are the same. Otherwise, <span style="color:#2e74b5;">const</span> value parameters should appear only on the definition, not on the declaration. Let&#8217;s see why. </p> <p>Putting the <span style="color:#2e74b5;">const</span> on a value parameter in a function declaration is irrelevant <em>outside</em> the function—it makes no difference to the caller and can only confuse readers. To the compiler, the function signature is the same whether you include this <span style="color:#2e74b5;">const</span> in front of a value parameter or not. For example: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// value parameter: top-level const is not part of function signature<br />int f( int );<br />int f( const int ); // <span style="text-decoration:underline;">redeclares</span> f(int): this is the same function<br /><br />// non-value parameter: top-level const is part of function signature<br />int g( int&amp; );<br />int g( const int&amp; ); // overloads g(int&amp;): these are two functions<span style="color:#2e74b5;"> </span></code></pre> </p> <p>But putting the <span style="color:#2e74b5;">const</span> on the value parameter does make a difference to how it can be used <em>inside</em> the function&#8217;s actual definition. Remember that, inside a function, the parameters are just the first set of local variables, so putting a <span style="color:#2e74b5;">const</span> on a value parameter simply means that the function can&#8217;t modify its local variable, which only happens to be a parameter. Here&#8217;s an example that declares and then defines the same function <span style="color:#2e74b5;">f</span>: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>int f( int ); // declaration: no const<br /><br />int f( const int i ) { // definition: use const to express "read-only"<br /><br /> vector&lt;int&gt; v;<br /> v.push_back(i); // ok, only reads from i<br /><br /> i = 42; // error, attempts to modify i<br /><br />} </code></pre> </p> <blockquote> <p><strong>Guideline:</strong> Consider not writing <strong>const</strong> on pass-by-value function parameters when only forward-declaring a function. You can always add it on the definition to express a read-only parameter. </p> </blockquote> <h3>2. get_point and get_num_points should be const.<br /> </h3> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code> point get_point( const int i ) { return points[i]; }<br /><br /> int get_num_points() { return points.size(); } </code></pre> </p> <p>These functions should be marked <span style="color:#2e74b5;">const</span>, because they don&#8217;t change the state of the object. </p> <h3>3. get_area should be const.<br /> </h3> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code> double get_area() {<br /> if( area &lt; 0 ) // if not yet calculated and cached<br /> calc_area(); // calculate now<br /> return area;<br /> } </code></pre> </p> <p>Even though this function modifies the object&#8217;s internal state, we should consider making it <span style="color:#2e74b5;">const</span>. Why? Because this function does not modify the object&#8217;s <em>observable</em> state; we are doing some caching here, but that&#8217;s an internal implementation detail and the object is logically <span style="color:#2e74b5;">const</span> even if it isn&#8217;t physically <span style="color:#2e74b5;">const</span>. </p> <h3>4. Therefore calc_area should also be const.<br /> </h3> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code> void calc_area() {<br /> area = 0;<br /> vector&lt;point&gt;::iterator i;<br /> for( i = begin(points); i != end(points); ++i )<br /> area += /* some work using *i */;<br /> } </code></pre> </p> <p>Once we make <span style="color:#2e74b5;">get_area</span> be <span style="color:#2e74b5;">const</span>, this private helper function ought also to be <span style="color:#2e74b5;">const</span>. </p> <p>In turn, once you make this function <span style="color:#2e74b5;">const</span>, the compiler will tell you that you also need to do something about the member variable <span style="color:#2e74b5;">area</span>, which should be: </p> <ul> <li>declared <span style="color:#2e74b5;">mutable</span>, so that it&#8217;s writable in a <span style="color:#2e74b5;">const</span> member function; and </li> <li>synchronized using a <span style="color:#2e74b5;">mutex</span> or made <span style="color:#2e74b5;">atomic&lt;&gt;</span>, so that it&#8217;s concurrency-safe, as discussed in GotW #6a. </li> </ul> <h3>5. Also, calc_area should use a const_iterator.<br /> </h3> <p>The iterator should not change the state of the <span style="color:#2e74b5;">points</span> collection, and so it ought to be a <span style="color:#2e74b5;">const_iterator</span>. We&#8217;re now forced to make this change anyway if we&#8217;re making <span style="color:#2e74b5;">calc_area</span> be a <span style="color:#2e74b5;">const</span> member function, but note that if we had said <span style="color:#2e74b5;">auto</span> for the iterator&#8217;s type we wouldn&#8217;t have had to make any change at all. While we&#8217;re at it, the <span style="color:#2e74b5;">for</span> loop inside <span style="color:#2e74b5;">calc_area</span>: It should prefer to use the range-based <span style="color:#2e74b5;">for</span> loop, as well as <span style="color:#2e74b5;">auto</span>. </p> <p>Combining all that, we get this simpler and <span style="color:#2e74b5;">const</span>-correct code: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code> for( auto&amp; pt : points )<br /> area += /* some work using pt */; </code></pre> </p> <blockquote> <p><strong>Guideline:</strong> Prefer declaring variables using <strong>auto</strong>. </p> </blockquote> <blockquote> <p><strong>Guideline:</strong> Prefer range-based <strong>for</strong> loops to naked iterator-incrementing <strong>for</strong> loops when visiting the elements of the range in order. </p> </blockquote> <h3>6. area should be mutable and synchronized.<br /> </h3> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code> double area; </code></pre> </p> <p>As noted already, in conjunction with the other changes the internal cache variable will <span style="color:#2e74b5;">area</span> now want to be <span style="color:#2e74b5;">mutable </span>so that it can be used correctly and safely inside <span style="color:#2e74b5;">const</span> member functions, and because it is now a shared variable potentially used by multiple concurrent <span style="color:#2e74b5;">const</span> operations it must also be synchronized—protected with a mutex or made <span style="color:#2e74b5;">atomic</span>. </p> <p><strong>Bonus Question: Before reading on, which should it be: Protected by a mutex? or made atomic&lt;double&gt;?<br /> </strong></p> <p>Have you thought about it? All right, let&#8217;s continue… </p> <p>Both work, but a mutex is usually overkill for a single variable. </p> <p>Option 1 is to use a mutex in the perhaps-soon-to-be-canonical &#8220;<span style="color:#2e74b5;">mutable mutex mutables</span>&#8221; pattern: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// Option 1: Use a mutex <br /><br /> double get_area() const {<br /> auto lock = unique_lock&lt;mutex&gt;{mutables};<br /> if( area &lt; 0 ) // if not yet calculated and cached<br /> calc_area(); // calculate now<br /> return area;<br /> }<br /><br />private:<br /> // ...<br /> mutable mutex mutables; // canonical pattern: mutex that<br /> mutable double area; // covers all mutable members </code></pre> </p> <p>Option 1 generalizes well if you add more data members in the future. However, it&#8217;s also more invasive and generalizes less well if you add more <span style="color:#2e74b5;">const</span> member functions in the future that use <span style="color:#2e74b5;">area</span>, because they will all have to remember to acquire a lock on the mutex before using <span style="color:#2e74b5;">area</span>. </p> <p>Option 2 is to just change <span style="color:#2e74b5;">double</span> to <span style="color:#2e74b5;">mutable atomic&lt;double&gt;</span>. This is attractive because the &#8220;<span style="color:#2e74b5;">mutable</span> part&#8221; of <span style="color:#2e74b5;">polygon</span> is just a single variable. That can work, but you have to be careful because that&#8217;s not the only necessary change, for two reasons: </p> <ul> <li>The minor reason is that <span style="color:#2e74b5;">atomic&lt;double&gt;</span> doesn&#8217;t support <span style="color:#2e74b5;">+=</span>, so if we only change <span style="color:#2e74b5;">area</span>&#8216;s type then <span style="color:#2e74b5;">calc_area</span> will no longer compile. That can be worked around, but leads us to the major reason… </li> <li>The major reason is that, because <span style="color:#2e74b5;">calc_area</span> is a compound operation and must be safe to run on multiple threads concurrently, we must restructure <span style="color:#2e74b5;">calc_area</span> to be safe to run concurrently. In particular it should not perform intermediate updates to <span style="color:#2e74b5;">area</span>, and should ensure that multiple competing concurrent updates to <span style="color:#2e74b5;">area</span> don&#8217;t cause overwrites that lose written values. </li> </ul> <p>There are several ways to do it, but the simplest is probably to allow benign redundant recalculations in the case of concurrent calls to <span style="color:#2e74b5;">calc_area</span>, on the grounds that it&#8217;s probably no worse than blocking the concurrent calls which would have to wait anyway. </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>// Option 2: Use an atomic<br /><br /> void calc_area() const {<br /> auto tmp = 0.0; // do all the work off to the side<br /> for( auto&amp; pt : points )<br /> tmp += /* some work using pt */;<br /> area = tmp; // then commit with a single write<br /> }<br /><br />private:<br /> // ...<br /> mutable atomic&lt;double&gt; area; </code></pre> </p> <p>Notice that concurrent <span style="color:#2e74b5;">const</span> operations that call to <span style="color:#2e74b5;">calc_area</span> can still overlap and overwrite each other&#8217;s results, but that&#8217;s benign because they&#8217;re <em>concurrent <span style="color:#2e74b5;">const</span> operations</em> so they will all calculate the same value. Also, concurrent <span style="color:#2e74b5;">calc_area</span> calls use the shared <span style="color:#2e74b5;">points</span> variable in a loop which should make us mentally check that it doesn&#8217;t cause cache contention, but because they&#8217;re all readers it won&#8217;t and so this too is fine. </p> <h3>7. operator+&#8217;s rhs parameter should be a reference to const.<br /> </h3> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>polygon operator+( polygon&amp; lhs, polygon&amp; rhs ) { </code></pre> </p> <p>The <span style="color:#2e74b5;">rhs</span> parameter should be passed by reference to <span style="color:#2e74b5;">const</span>, of course. </p> <blockquote> <p><strong>Guideline:</strong> Prefer passing a read-only parameter by <strong>const&amp;</strong> if you are only going to read from it (not make a copy of it). </p> </blockquote> <p>&#8220;But wait!&#8221; I can just hear some of you saying, &#8220;you forgot about <span style="color:#2e74b5;">lhs</span>! Shouldn&#8217;t it be <span style="color:#2e74b5;">const&amp;</span> too?&#8221; Actually, not so much: </p> <h3>8. operator+&#8217;s lhs parameter should be passed by value.<br /> </h3> <p>The key point is that we&#8217;re going to copy from it anyway, in this case immediately: </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code> auto ret = lhs; </code></pre> </p> <p>When you&#8217;re in the special case of &#8220;read-only parameter that you&#8217;re going to take copy of anyway,&#8221; there are several ways to accept the parameter, which I&#8217;ll cover in detail in another GotW. For now, suffice it to say that usually you shouldn&#8217;t overthink these options, and just use pass-by-value as the simplest method, which offers some advantages that we also touched on in GotW #4: </p> <ul> <li>If the caller passes a named <span style="color:#2e74b5;">polygon</span> object (an lvalue), there&#8217;s no difference. Both pass-by-<span style="color:#2e74b5;">const&amp;</span> followed by an explicit copy and pass-by-value will perform one copy. </li> <li> <div>If the caller passes a temporary <span style="color:#2e74b5;">polygon</span> object (an rvalue), the compiler automatically move-constructs <span style="color:#2e74b5;">lhs</span> from that, which probably makes no difference for a small type like <span style="color:#2e74b5;">polygon</span> but can be considerably cheaper for many types. </div> <blockquote> <p><strong>Guideline:</strong> Prefer passing a read-only parameter by value if you&#8217;re going to make a copy of the parameter anyway, because it enables move from rvalue arguments. </p> </blockquote> </li> </ul> <h3>9. Also in operator+, last should be const.<br /> </h3> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code> auto last = rhs.get_num_points();<br /> for( auto i = 0; i &lt; last; ++i ) // concatenate<br /> ret.add_point( rhs.get_point(i) );<br /> return ret;<br />} </code></pre> </p> <p>Since <span style="color:#2e74b5;">last</span> should never change, prefer to say so by making it <span style="color:#2e74b5;">const</span>. </p> <blockquote> <p><strong>Guideline:</strong> Prefer to make variables, including locals, <strong>const</strong> if they should not change. </p> </blockquote> <p>Incidentally, notice that once we make <span style="color:#2e74b5;">rhs</span> a reference-to-<span style="color:#2e74b5;">const</span> parameter as noted above, we see another reason why <span style="color:#2e74b5;">get_point</span> should be a <span style="color:#2e74b5;">const</span> member function. </p> <h3>10. f&#8217;s const_cast may give undefined behavior, and is morally wrong anyway.<br /> </h3> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>void f( const polygon&amp; poly ) {<br /> const_cast&lt;polygon&amp;&gt;(poly).add_point( {0,0} );<br />} </code></pre> </p> <p>Bonus: The result of the <span style="color:#2e74b5;">const_cast</span> is undefined if the referenced object was declared as <span style="color:#2e74b5;">const</span>—which it is in the case of <span style="color:#2e74b5;">f(cpoly)</span> below. </p> <p>The parameter isn&#8217;t really <span style="color:#2e74b5;">const</span>, so don&#8217;t declare it as <span style="color:#2e74b5;">const</span> and then try to modify it anyway. Lying to the compiler, never mind to the caller, is a bad idea, never mind morally reprehensible in most value systems. </p> <h3>11. g&#8217;s const is illegal and useless.<br /> </h3> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>void g( polygon&amp; const poly ) { poly.add_point( {1,1} ); } </code></pre> </p> <p>This <span style="color:#2e74b5;">const</span> is illegal; you can&#8217;t apply <span style="color:#2e74b5;">const</span> directly to the reference itself, besides which references are already <span style="color:#2e74b5;">const</span> inasmuch as they cannot be reseated to refer to a different object. </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>void h( polygon* const poly ) { poly-&gt;add_point( {2,2} ); } </code></pre> </p> <p>Note that <span style="color:#2e74b5;">h</span>&#8216;s <span style="color:#2e74b5;">const</span> merely ensures that <span style="color:#2e74b5;">h</span>&#8216;s body won&#8217;t modify the pointer value. This is the same as the <span style="color:#2e74b5;">const</span> value parameters in <span style="color:#2e74b5;">add_point</span> and <span style="color:#2e74b5;">get_point</span>, and perfectly fine on the definition. </p> <h3>12. Examining the mainline.<br /> </h3> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>int main() {<br /> polygon poly;<br /> const polygon cpoly;<br /><br /> f(poly); </code></pre> </p> <p>This is fine. </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code> f(cpoly); </code></pre> </p> <p>As already noted, this causes undefined results when <span style="color:#2e74b5;">f</span> tries to cast away the <span style="color:#2e74b5;">const</span>-ness of its parameter and then modify it. </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code> g(poly); </code></pre> </p> <p>This is fine. </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code> h(&amp;poly);<br />} </code></pre> </p> <p>This is fine. </p> <h3>Summary<br /> </h3> <p>Here is a revised version of the code that corrects the <span style="color:#2e74b5;">const</span> issues noted above, but does not attempt to correct any other poor style. Note that because of the <span style="color:#2e74b5;">atomic</span> member, which is not copyable, we now provide <span style="color:#2e74b5;">polygon</span>&#8216;s copy and move operations explicitly. </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>class polygon {<br />public:<br /> polygon() : area{-1} {}<br /><br /> polygon( const polygon&amp; other ) : points{other.points}, area{-1} { }<br /><br /> polygon( polygon&amp;&amp; other ) <br /> : points{move(other.points)}, area{other.area.load()}<br /> { other.area = -1; }<br /><br /> polygon&amp; operator=( const polygon&amp; other )<br /> { points = other.points; area = -1; return *this; }<br /><br /> polygon&amp; operator=( polygon&amp;&amp; other ) {<br /> points = move(other.points);<br /> area = other.area.load();<br /> other.area = -1;<br /> return *this;<br /> }<br /><br /> void add_point( point pt ) <br /> { area = -1; points.push_back(pt); }<br /><br /> point get_point( int i ) const { return points[i]; }<br /><br /> int get_num_points() const { return points.size(); }<br /><br /> double get_area() const {<br /> if( area &lt; 0 ) // if not yet calculated and cached<br /> calc_area(); // calculate now<br /> return area;<br /> }<br /><br />private:<br /> void calc_area() const {<br /> auto tmp = 0.0;<br /> for( auto&amp; pt : points )<br /> tmp += /* some work using pt */;<br /> area = tmp;<br /> }<br /><br /> vector&lt;point&gt; points;<br /> mutable atomic&lt;double&gt; area;<br />};<br /><br />polygon operator+( polygon lhs, const polygon&amp; rhs ) {<br /> const auto last = rhs.get_num_points();<br /> for( auto i = 0; i &lt; last; ++i ) // concatenate<br /> lhs.add_point( rhs.get_point(i) );<br /> return lhs;<br />}<br /><br />void f( polygon&amp; poly ) { poly.add_point( {0,0} ); }<br /><br />void g( polygon&amp; poly ) { poly.add_point( {1,1} ); }<br /><br />void h( polygon* poly ) { poly-&gt;add_point( {2,2} ); }<br /><br />int main() {<br /> auto poly = polygon{};<br /><br /> f(poly);<br /> g(poly);<br /> h(&amp;poly);<br />} </code></pre> </p> <h2>Acknowledgments<br /> </h2> <p>Thanks in particular to the following for their feedback to improve this article: mttpd, Vincent Lascaux, jlehrer, Motti, Fernando Pelliccioni, Leo, Mathias Stearn.</p> </div><!-- .entry-content --> <footer class="entry-footer"> <div class="entry-meta"> <span class="byline"> <a href="https://herbsutter.com/author/herbsutter/" title="Posts by Herb Sutter" rel="author">Herb Sutter</a> </span> <span class="cat-links"> <a href="https://herbsutter.com/category/c/" rel="category tag">C++</a> </span><!-- .cat-links --> <span class="comments-link"><a href="https://herbsutter.com/2013/05/28/gotw-6b-solution-const-correctness-part-2/#comments">54 Comments</a></span><!-- .comments-link --> <span class="published-on"> <a href="https://herbsutter.com/2013/05/28/gotw-6b-solution-const-correctness-part-2/" rel="bookmark"><time class="entry-date published" datetime="2013-05-28T16:05:43-08:00">2013-05-28</time><time class="updated" datetime="2013-12-23T06:30:00-08:00">2013-12-23</time></a> </span> <span class="word-count">9 Minutes</span> </div><!-- .entry-meta --> </footer><!-- .entry-footer --> </article><!-- #post-## --> <article id="post-2020" class="post-2020 post type-post status-publish format-standard hentry category-c"> <header class="entry-header"> <h1 class="entry-title"><a href="https://herbsutter.com/2013/05/25/c-and-beyond-my-material-for-december-and-early-bird-registration-through-june-9/" rel="bookmark">C++ and Beyond: My material for December, and early-bird registration (through June&nbsp;9)</a></h1> </header><!-- .entry-header --> <div class="entry-content"> <p>If you&#8217;re thinking of coming to <a href="http://cppandbeyond.com"><em>C++ and Beyond</em></a> this December, consider <a href="http://cppandbeyond.com/2013/05/24/early-bird-registration-rates-expire-june-9/">registering in the next two weeks to get the $300 discount</a>. </p> <p>I&#8217;ve <a href="http://cppandbeyond.com/2013/05/25/2013-session-c11-and-c14-style/">just announced</a> that much (and possibly all) of my material will be in heavily interactive sessions about <strong>modern C++11/C++14 style and idioms</strong>, covering the &#8220;complete C++11 package&#8221; that we&#8217;re calling C++14. We know C++14&#8217;s shape because as of the Bristol meeting in April it&#8217;s now feature-complete, and only international commenting and other fine-tuning remains. We know C++14 is real and that at least two of the major commercial compilers will be implementing all of C++14 by next year. And we know C++14 really does complete C++11, and it&#8217;s compelling enough that it&#8217;s made me <a href="https://herbsutter.com/2013/05/04/guru-of-the-week-and-the-exceptional-c-series/">rewrite my <em>Guru of the Week</em> series and <em>Exceptional C++</em> books, targeting C++14</a>. From the description: </p> <blockquote> <p>This session will cover modern and current C++ style, focusing on C++14. I&#8217;ll demonstrate how major features and idioms from C++98 are now entirely replaced or subsumed and should be used no more; how other major features and idioms have been dramatically improved to the point where you code is cleaner and safer and you&#8217;ll even <em>think</em> in a different style; and how pervasive styles as common as variable declarations are changed forever, and not just for style but for serious technical safety and efficiency benefits. For one thing, you&#8217;ll never look at &#8216;auto&#8217; the same way again (there, I said it; bring out the lederhosen and pitchforks! or attend the session and challenge in person to dig deep into the good reasons for the new reality). </p> </blockquote> <p>Scott has announced one of his prospective talks: <a href="http://cppandbeyond.com/2013/05/08/prospective-session-concurrent-data-structures-and-standard-c/"><strong>&#8220;Concurrent Data Structures and Standard C++.&#8221;</strong></a> From his description: </p> <blockquote> <p>Concurrent data structures permit multiple writers to simultaneously modify a single data structure. Used properly, they can avoid scalability bottlenecks in multithreaded systems. Used improperly, they can decrease program performance. </p> </blockquote> <blockquote> <p>There are no concurrent data structures in the C++98 standard library. The C++11 standard library is similarly bare, and C++14 is unlikely to change that.  Nevertheless, concurrent data structures for C++ developers are widely available from sources such as <a href="http://msdn.microsoft.com/en-us/library/dd492418.aspx">Microsoft&#8217;s PPL</a>, <a href="http://threadingbuildingblocks.org/">Intel&#8217;s TBB</a>, and <a href="http://www.boost.org/">Boost</a>. In this talk, I&#8217;ll examine the motivation and use cases for concurrent data structures, discuss their limitations, survey offerings common to PPL and TBB, and contrast concurrent APIs with those of seemingly similar serial counterparts (e.g., <span style="font-family:Courier New;font-size:10pt;">concurrent_vector</span> vs. <span style="font-family:Courier New;font-size:10pt;">std::vector</span>). I&#8217;ll also explain why writing your own concurrent data structure is much more complicated and error-prone than most people initially imagine.  (If you&#8217;re not familiar with the ABA problem, this presentation will explain why you should be.) </p> </blockquote> <p>For more information, <a href="http://cppandbeyond.com/2013/05/24/early-bird-registration-rates-expire-june-9/">see the C&amp;B blog</a>. I look forward to meeting and re-meeting many of you at C&amp;B. The attendance is limited to 64 this year, and it will be a delightful technical C++-fest in a <a href="http://cppandbeyond.com/salish-lodge-information/">cozy lodge far from distractions and with lots of fireplaces</a>.</p> </div><!-- .entry-content --> <footer class="entry-footer"> <div class="entry-meta"> <span class="byline"> <a href="https://herbsutter.com/author/herbsutter/" title="Posts by Herb Sutter" rel="author">Herb Sutter</a> </span> <span class="cat-links"> <a href="https://herbsutter.com/category/c/" rel="category tag">C++</a> </span><!-- .cat-links --> <span class="comments-link"><a href="https://herbsutter.com/2013/05/25/c-and-beyond-my-material-for-december-and-early-bird-registration-through-june-9/#comments">23 Comments</a></span><!-- .comments-link --> <span class="published-on"> <a href="https://herbsutter.com/2013/05/25/c-and-beyond-my-material-for-december-and-early-bird-registration-through-june-9/" rel="bookmark"><time class="entry-date published" datetime="2013-05-25T16:20:46-08:00">2013-05-25</time><time class="updated" datetime="2013-08-19T22:35:30-08:00">2013-08-19</time></a> </span> <span class="word-count">2 Minutes</span> </div><!-- .entry-meta --> </footer><!-- .entry-footer --> </article><!-- #post-## --> <article id="post-2012" class="post-2012 post type-post status-publish format-standard hentry category-c"> <header class="entry-header"> <h1 class="entry-title"><a href="https://herbsutter.com/2013/05/24/lost-two-comments/" rel="bookmark">Lost two comments</a></h1> </header><!-- .entry-header --> <div class="entry-content"> <p>As mentioned in my GotW kickoff post, I&#8217;m experimenting with software and a workflow that lets me maintain a single source document and use it to produce the work in multiple targets, in particular to post to the blog here, to produce print books, and to produce e-books.</p> <p>However, there have been kinks. In particular, on the blog I sometimes repost an update to an already-posted solution, and though it usually correctly updates the existing one, sometimes it chooses to create a new post instead and I have to delete the duplicate. That happened this morning, and I had a remove an accidental duplicate of the GotW #6a solution post.</p> <p>Unfortunately, people had already left two comments on that duplicate post, and those comments seem to have got lost in the ether. I apologize for that; I think this is the first time I&#8217;ve ever lost someone&#8217;s comment, but it did happen this morning as I&#8217;m still working out kinks in the software. I believe I have a workaround and that it won&#8217;t happen again.</p> </div><!-- .entry-content --> <footer class="entry-footer"> <div class="entry-meta"> <span class="byline"> <a href="https://herbsutter.com/author/herbsutter/" title="Posts by Herb Sutter" rel="author">Herb Sutter</a> </span> <span class="cat-links"> <a href="https://herbsutter.com/category/c/" rel="category tag">C++</a> </span><!-- .cat-links --> <span class="comments-link"><a href="https://herbsutter.com/2013/05/24/lost-two-comments/#comments">5 Comments</a></span><!-- .comments-link --> <span class="published-on"> <a href="https://herbsutter.com/2013/05/24/lost-two-comments/" rel="bookmark"><time class="entry-date published" datetime="2013-05-24T11:25:48-08:00">2013-05-24</time><time class="updated" datetime="2013-08-19T22:35:55-08:00">2013-08-19</time></a> </span> <span class="word-count">1 Minute</span> </div><!-- .entry-meta --> </footer><!-- .entry-footer --> </article><!-- #post-## --> <article id="post-2002" class="post-2002 post type-post status-publish format-standard hentry category-c"> <header class="entry-header"> <h1 class="entry-title"><a href="https://herbsutter.com/2013/05/24/gotw-6b-const-correctness-part-2/" rel="bookmark">GotW #6b: Const-Correctness, Part&nbsp;2</a></h1> </header><!-- .entry-header --> <div class="entry-content"> <p><span style="color:#5a5a5a;"><em>const and mutable are powerful tools for writing safer code. Use them consistently.</em></span> </p> <h1>Problem<br /> </h1> <h2>Guru Question<br /> </h2> <p>In the following code, add or remove <span style="color:#2e74b5;">const</span> (including minor variants and related keywords) wherever appropriate. Note: Don&#8217;t comment on or change the structure of this program. It&#8217;s contrived and condensed for illustration only. </p> <p>For bonus points: In what places are the program&#8217;s results undefined or uncompilable due to <span style="color:#2e74b5;">const</span> errors? </p> <p style="background:#ffffcc;margin-left:14pt;"> <pre><code>class polygon {<br />public:<br /> polygon() : area{-1} {}<br /><br /> void add_point( const point pt ) { area = -1;<br /> points.push_back(pt); }<br /><br /> point get_point( const int i ) { return points[i]; }<br /><br /> int get_num_points() { return points.size(); }<br /><br /> double get_area() {<br /> if( area &lt; 0 ) // if not yet calculated and cached<br /> calc_area(); // calculate now<br /> return area;<br /> }<br /><br />private:<br /> void calc_area() {<br /> area = 0;<br /> vector&lt;point&gt;::iterator i;<br /> for( i = begin(points); i != end(points); ++i )<br /> area += /* some work using *i */;<br /> }<br /><br /> vector&lt;point&gt; points;<br /> double area;<br />};<br /><br />polygon operator+( polygon&amp; lhs, polygon&amp; rhs ) {<br /> auto ret = lhs;<br /> auto last = rhs.get_num_points();<br /> for( auto i = 0; i &lt; last; ++i ) // concatenate<br /> ret.add_point( rhs.get_point(i) );<br /> return ret;<br />}<br /><br />void f( const polygon&amp; poly ) {<br /> const_cast&lt;polygon&amp;&gt;(poly).add_point( {0,0} );<br />}<br /><br />void g( polygon&amp; const poly ) { poly.add_point( {1,1} ); }<br /><br />void h( polygon* const poly ) { poly-&gt;add_point( {2,2} ); }<br /><br />int main() {<br /> polygon poly;<br /> const polygon cpoly;<br /><br /> f(poly);<br /> f(cpoly);<br /> g(poly);<br /> h(&amp;poly);<br />} </code></pre></p> </div><!-- .entry-content --> <footer class="entry-footer"> <div class="entry-meta"> <span class="byline"> <a href="https://herbsutter.com/author/herbsutter/" title="Posts by Herb Sutter" rel="author">Herb Sutter</a> </span> <span class="cat-links"> <a href="https://herbsutter.com/category/c/" rel="category tag">C++</a> </span><!-- .cat-links --> <span class="comments-link"><a href="https://herbsutter.com/2013/05/24/gotw-6b-const-correctness-part-2/#comments">8 Comments</a></span><!-- .comments-link --> <span class="published-on"> <a href="https://herbsutter.com/2013/05/24/gotw-6b-const-correctness-part-2/" rel="bookmark"><time class="entry-date published updated" datetime="2013-05-24T07:43:05-08:00">2013-05-24</time></a> </span> <span class="word-count">1 Minute</span> </div><!-- .entry-meta --> </footer><!-- .entry-footer --> </article><!-- #post-## --> <article id="post-2000" class="post-2000 post type-post status-publish format-standard hentry category-c"> <header class="entry-header"> <h1 class="entry-title"><a href="https://herbsutter.com/2013/05/24/gotw-6a-const-correctness-part-1-3/" rel="bookmark">GotW #6a Solution: Const-Correctness, Part&nbsp;1</a></h1> </header><!-- .entry-header --> <div class="entry-content"> <p><span style="color:#5a5a5a;"><em>const and mutable have been in C++ for many years. How well do you know what they mean today?<br /> </em></span></p> <h1>Problem</h1> <h2>JG Question</h2> <p>1. What is a &#8220;shared variable&#8221;?</p> <h2>Guru Questions</h2> <p>2. What do <span style="color:#2e74b5;">const</span> and <span style="color:#2e74b5;">mutable</span> mean on shared variables?</p> <p>3. How are <span style="color:#2e74b5;">const</span> and <span style="color:#2e74b5;">mutable</span> different in C++98 and C++11?</p> <h1>Solution</h1> <h2>1. What is a &#8220;shared variable&#8221;?</h2> <p>A &#8220;shared variable&#8221; is one that could be accessed from more than one thread at the same time.</p> <p>This concept is important in the C++ memory model. For example, the C++ memory model (the core of which is described in ISO C++ §1.10) prohibits the invention of a write to a &#8220;potentially shared memory location&#8221; that would not have been written to in a sequentially consistent execution of the program, and the C++ standard library refers to this section when it prohibits &#8220;modify[ing] objects accessible by [other] threads&#8221; through a <span style="color:#2e74b5;">const</span> function, as we will see in #2.</p> <h2>2. What do const and mutable mean on shared variables?</h2> <p>Starting with C++11, <span style="color:#2e74b5;">const</span> on a variable that is possibly shared means &#8220;read-only or as good as read-only&#8221; for the purposes of concurrency. Concurrent <span style="color:#2e74b5;">const</span> operations on the same object are required to be safe without the calling code doing external synchronization.</p> <p>If you are implementing a type, unless you know objects of the type can never be shared (which is generally impossible), this means that each of your <span style="color:#2e74b5;">const</span> member functions must be either:</p> <ul> <li>truly physically/bitwise <span style="color:#2e74b5;">const</span> with respect to this object, meaning that they perform no writes to the object&#8217;s data; or else</li> <li>internally synchronized so that if it does perform any actual writes to the object&#8217;s data, that data is correctly protected with a mutex or equivalent (or if appropriate are <span style="color:#2e74b5;">atomic&lt;&gt;</span>) so that any possible concurrent <span style="color:#2e74b5;">const</span> accesses by multiple callers can&#8217;t tell the difference.</li> </ul> <p>Types that do not respect this cannot be used with the standard library, which requires that:</p> <blockquote><p>&#8220;… to prevent data races (1.10). … [a] C++ standard library function shall not directly or indirectly modify objects (1.10) accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function&#8217;s non-<strong>const</strong> arguments, including <strong>this</strong>.&#8221;—ISO C++ §17.6.5.9</p></blockquote> <p>Similarly, writing <span style="color:#2e74b5;">mutable</span> on a member variable means what it has always meant: The variable is &#8220;writable but logically <span style="color:#2e74b5;">const</span>.&#8221; Note what this implies:</p> <ul> <li>The &#8220;logically <span style="color:#2e74b5;">const</span>&#8221; part now means &#8220;can be used safely by multiple concurrent <span style="color:#2e74b5;">const</span> operations.&#8221;</li> <li>The &#8220;<span style="color:#2e74b5;">mutable</span>&#8221; and &#8220;writable&#8221; part further means that some <span style="color:#2e74b5;">const</span> operations may actually be writers of the shared variable, which means it&#8217;s inherently got to be correct to read and write concurrently, so it should be protected with a mutex or similar, or made <span style="color:#2e74b5;">atomic&lt;&gt;</span>.</li> </ul> <p>In general, remember:</p> <blockquote><p><strong>Guideline:</strong> Remember the &#8220;M&amp;M rule&#8221;: For a member variable, <strong>mutable</strong> and <strong>mutex</strong> (or <strong>atomic)</strong> go together.</p></blockquote> <p>This applies in both directions, to wit:</p> <blockquote><p><strong>(1) For a member variable, mutable implies mutex (or equivalent):</strong> A <strong>mutable</strong> member variable is presumed to be a mutable shared variable and so must be synchronized internally—protected with a <strong>mutex,</strong> made <strong>atomic,</strong> or similar.</p></blockquote> <blockquote><p><strong>(2) For a member variable, mutex (or similar synchronization type) implies mutable<span style="color:#2e74b5;">:</span></strong> A member variable that is itself of a synchronization type, such as a <strong>mutex</strong> or a condition variable, naturally wants to be <strong>mutable,</strong> because you will want to use it in a non-<strong>const</strong> way (e.g., take a <strong>std::lock_guard&lt;mutex&gt;</strong>) inside concurrent <strong>const</strong> member functions.</p></blockquote> <p>We&#8217;ll see an example of (2) in Part 2, GotW #6b.</p> <h2>3. How are const and mutable different in C++98 and C++11?</h2> <p>First, let&#8217;s be clear: C++98 single-threaded code still works. C++11 has excellent C++98 compatibility, and even though the meaning of <span style="color:#2e74b5;">const</span> has evolved, C++98 single-threaded code that uses the old &#8220;logically <span style="color:#2e74b5;">const</span>&#8221; meaning of <span style="color:#2e74b5;">const</span> is still valid.</p> <p>With C++98, we taught a generation of C++ developers that &#8220;<span style="color:#2e74b5;">const</span> means logically <span style="color:#2e74b5;">const</span>, not physically/bitwise <span style="color:#2e74b5;">const</span>.&#8221; That is, in C++98 we taught that <span style="color:#2e74b5;">const</span> meant only that the observable state of the object (say, via its non-private member functions) should not change as far as the caller could tell, but its internal bits might change in order to update counters and instrumentation and other data not accessible via the type&#8217;s public or protected interface.</p> <p>That definition is not sufficient for concurrency. With C++11 and onward, which now includes a concurrency memory model and thread safety specification for the standard library, this is now much simpler: <span style="color:#2e74b5;">const</span> now really does mean &#8220;read-only, or safe to read concurrently&#8221;—either truly physically/bitwise <span style="color:#2e74b5;">const</span>, or internally synchronized so that any actual writes are synchronized with any possible concurrent <span style="color:#2e74b5;">const</span> accesses so the callers can&#8217;t tell the difference.</p> <p>Although existing C++98-era types still work just fine in C++98-era single-threaded code for compatibility, those types and any new ones you write today should obey the new stricter requirement if they could be used on multiple threads. The good news is that most existing types already followed that rule, and code that relies on casting away <span style="color:#2e74b5;">const</span> and/or using <span style="color:#2e74b5;">mutable</span> data members in single-threaded code has already been generally questionable and relatively rare.</p> <h2>Summary</h2> <p>Don&#8217;t shoot yourself (or your fellow programmers) in the foot. Write <span style="color:#2e74b5;">const</span>-correct code.</p> <p>Using <span style="color:#2e74b5;">const</span> consistently is simply necessary for correctly-synchronized code. That by itself is ample reason to be consistently <span style="color:#2e74b5;">const</span>-correct, but there&#8217;s more: It lets you document interfaces and invariants far more effectively than any mere <span style="color:#2e74b5;">/* I promise not to change this */</span> comment can accomplish. It&#8217;s a powerful part of &#8220;design by contract.&#8221; It helps the compiler to stop you from accidentally writing bad code. It can even help the compiler generate tighter, faster, smaller code. That being the case, there&#8217;s no reason why you shouldn&#8217;t use it as much as possible, and every reason why you should.</p> <p>Remember that the correct use of <span style="color:#2e74b5;">mutable</span> is a key part of <span style="color:#2e74b5;">const</span>-correctness. If your class contains a member that could change even for <span style="color:#2e74b5;">const</span> objects and operations, make that member <span style="color:#2e74b5;">mutable</span> and protect it with a mutex or make it <span style="color:#2e74b5;">atomic</span>. That way, you will be able to write your class&#8217; <span style="color:#2e74b5;">const</span> member functions easily and correctly, and users of your class will be able to correctly create and use <span style="color:#2e74b5;">const</span> and non-<span style="color:#2e74b5;">const</span> objects of your class&#8217; type.</p> <p>It&#8217;s true that not all commercial libraries&#8217; interfaces are <span style="color:#2e74b5;">const</span>-correct. That isn&#8217;t an excuse for you to write <span style="color:#2e74b5;">const</span>-incorrect code, though. It is, however, one of the few good excuses to write <span style="color:#2e74b5;">const_cast</span>, plus a detailed comment nearby grumbling about the library vendor&#8217;s laziness and how you&#8217;re looking for a replacement product.</p> <h2>Acknowledgments</h2> <p>Thanks in particular to the following for their feedback to improve this article: mttpd, jlehrer, Chris Vine.</p> </div><!-- .entry-content --> <footer class="entry-footer"> <div class="entry-meta"> <span class="byline"> <a href="https://herbsutter.com/author/herbsutter/" title="Posts by Herb Sutter" rel="author">Herb Sutter</a> </span> <span class="cat-links"> <a href="https://herbsutter.com/category/c/" rel="category tag">C++</a> </span><!-- .cat-links --> <span class="comments-link"><a href="https://herbsutter.com/2013/05/24/gotw-6a-const-correctness-part-1-3/#comments">15 Comments</a></span><!-- .comments-link --> <span class="published-on"> <a href="https://herbsutter.com/2013/05/24/gotw-6a-const-correctness-part-1-3/" rel="bookmark"><time class="entry-date published" datetime="2013-05-24T07:40:37-08:00">2013-05-24</time><time class="updated" datetime="2013-05-26T09:38:32-08:00">2013-05-26</time></a> </span> <span class="word-count">4 Minutes</span> </div><!-- .entry-meta --> </footer><!-- .entry-footer --> </article><!-- #post-## --> <nav class="navigation posts-navigation" aria-label="Posts"> <h2 class="screen-reader-text">Posts navigation</h2> <div class="nav-links"><div class="nav-previous"><a href="https://herbsutter.com/2013/05/page/2/" >Older posts</a></div></div> </nav> </main><!-- #main --> </div><!-- #primary --> <div id="secondary" class="widget-area" role="complementary"> <aside id="search-4" class="widget widget_search"><form role="search" method="get" class="search-form" action="https://herbsutter.com/"> <label> <span class="screen-reader-text">Search for:</span> <input type="search" class="search-field" placeholder="Search &hellip;" value="" name="s" /> </label> <input type="submit" class="search-submit" value="Search" /> </form></aside><aside id="blog_subscription-3" class="widget widget_blog_subscription jetpack_subscription_widget"><h1 class="widget-title"><label for="subscribe-field">Follow by email</label></h1> <div class="wp-block-jetpack-subscriptions__container"> <form action="https://subscribe.wordpress.com" method="post" accept-charset="utf-8" data-blog="3379246" data-post_access_level="everybody" id="subscribe-blog" > <p id="subscribe-email"> <label id="subscribe-field-label" for="subscribe-field" class="screen-reader-text" > Email Address: </label> <input type="email" name="email" style="width: 95%; padding: 1px 10px" placeholder="Email Address" value="" id="subscribe-field" required /> </p> <p id="subscribe-submit" > <input type="hidden" name="action" value="subscribe"/> <input type="hidden" name="blog_id" value="3379246"/> <input type="hidden" name="source" value="https://herbsutter.com/2013/05/"/> <input type="hidden" name="sub-type" value="widget"/> <input type="hidden" name="redirect_fragment" value="subscribe-blog"/> <input type="hidden" id="_wpnonce" name="_wpnonce" value="c1038c5b8c" /> <button type="submit" class="wp-block-button__link" > Subscribe </button> </p> </form> </div> </aside><aside id="block-2" class="widget widget_block widget_media_image"> <figure class="wp-block-image size-medium is-resized is-style-default"><a href="https://herbsutter.files.wordpress.com/2024/03/herb-cppcon-2021.jpg"><img loading="lazy" width="300" height="230" src="https://herbsutter.files.wordpress.com/2024/03/herb-cppcon-2021.jpg?w=300" alt="" class="wp-image-5065" style="width:248px;height:auto" srcset="https://herbsutter.files.wordpress.com/2024/03/herb-cppcon-2021.jpg?w=300 300w, https://herbsutter.files.wordpress.com/2024/03/herb-cppcon-2021.jpg?w=600 600w, https://herbsutter.files.wordpress.com/2024/03/herb-cppcon-2021.jpg?w=150 150w" sizes="(max-width: 300px) 100vw, 300px" /></a></figure> </aside><aside id="block-3" class="widget widget_block widget_text"> <p class="has-small-font-size">I'm an author and speaker, and a programming language nerd whose focus is on enabling our program code to be both clean <em>and</em> fast. I've been writing about programming since 1993, usually about C++ or about concurrency and parallelism. I'm the designer or co-designer of a number of standardized ISO C++ language and library features. I've served as the chair of the <a href="https://isocpp.org/std/the-committee">ISO C++ standards committee</a> since 2002, and as the chair of the <a href="https://isocpp.org/about">Standard C++ Foundation</a> since 2012. I'm a technical fellow at <a href="https://www.citadelsecurities.com/">Citadel Securities</a>. This personal website expresses the opinions of none of those organizations.</p> </aside><aside id="archives-4" class="widget widget_archive"><h1 class="widget-title">Archives</h1> <ul> <li><a href='https://herbsutter.com/2025/02/'>February 2025</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2025/01/'>January 2025</a>&nbsp;(5)</li> <li><a href='https://herbsutter.com/2024/12/'>December 2024</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2024/11/'>November 2024</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2024/10/'>October 2024</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2024/09/'>September 2024</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2024/08/'>August 2024</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2024/07/'>July 2024</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2024/06/'>June 2024</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2024/04/'>April 2024</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2024/03/'>March 2024</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2024/02/'>February 2024</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2023/11/'>November 2023</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2023/10/'>October 2023</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2023/09/'>September 2023</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2023/08/'>August 2023</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2023/06/'>June 2023</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2023/04/'>April 2023</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2023/02/'>February 2023</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2022/12/'>December 2022</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2022/11/'>November 2022</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2022/10/'>October 2022</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2022/09/'>September 2022</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2021/10/'>October 2021</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2021/06/'>June 2021</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2021/05/'>May 2021</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2021/03/'>March 2021</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2021/02/'>February 2021</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2021/01/'>January 2021</a>&nbsp;(5)</li> <li><a href='https://herbsutter.com/2020/12/'>December 2020</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2020/11/'>November 2020</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2020/10/'>October 2020</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2020/09/'>September 2020</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2020/07/'>July 2020</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2020/06/'>June 2020</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2020/05/'>May 2020</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2020/04/'>April 2020</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2020/03/'>March 2020</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2020/02/'>February 2020</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2019/11/'>November 2019</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2019/10/'>October 2019</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2019/09/'>September 2019</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2019/07/'>July 2019</a>&nbsp;(5)</li> <li><a href='https://herbsutter.com/2019/06/'>June 2019</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2019/05/'>May 2019</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2019/04/'>April 2019</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2019/02/'>February 2019</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2018/11/'>November 2018</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2018/09/'>September 2018</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2018/07/'>July 2018</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2018/04/'>April 2018</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2017/11/'>November 2017</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2017/10/'>October 2017</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2017/09/'>September 2017</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2017/07/'>July 2017</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2017/06/'>June 2017</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2017/03/'>March 2017</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2017/02/'>February 2017</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2016/11/'>November 2016</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2016/09/'>September 2016</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2016/06/'>June 2016</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2016/03/'>March 2016</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2015/10/'>October 2015</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2015/09/'>September 2015</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2015/07/'>July 2015</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2015/06/'>June 2015</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2015/05/'>May 2015</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2015/04/'>April 2015</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2015/01/'>January 2015</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2014/12/'>December 2014</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2014/11/'>November 2014</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2014/10/'>October 2014</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2014/09/'>September 2014</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2014/08/'>August 2014</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2014/07/'>July 2014</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2014/05/'>May 2014</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2014/04/'>April 2014</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2014/03/'>March 2014</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2014/02/'>February 2014</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2014/01/'>January 2014</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2013/12/'>December 2013</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2013/11/'>November 2013</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2013/10/'>October 2013</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2013/09/'>September 2013</a>&nbsp;(6)</li> <li><a href='https://herbsutter.com/2013/08/'>August 2013</a>&nbsp;(5)</li> <li><a href='https://herbsutter.com/2013/07/'>July 2013</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2013/06/'>June 2013</a>&nbsp;(7)</li> <li><a href='https://herbsutter.com/2013/05/' aria-current="page">May 2013</a>&nbsp;(22)</li> <li><a href='https://herbsutter.com/2013/04/'>April 2013</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2013/03/'>March 2013</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2013/02/'>February 2013</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2013/01/'>January 2013</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2012/12/'>December 2012</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2012/11/'>November 2012</a>&nbsp;(6)</li> <li><a href='https://herbsutter.com/2012/10/'>October 2012</a>&nbsp;(5)</li> <li><a href='https://herbsutter.com/2012/09/'>September 2012</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2012/08/'>August 2012</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2012/07/'>July 2012</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2012/06/'>June 2012</a>&nbsp;(7)</li> <li><a href='https://herbsutter.com/2012/05/'>May 2012</a>&nbsp;(5)</li> <li><a href='https://herbsutter.com/2012/04/'>April 2012</a>&nbsp;(17)</li> <li><a href='https://herbsutter.com/2012/03/'>March 2012</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2012/02/'>February 2012</a>&nbsp;(5)</li> <li><a href='https://herbsutter.com/2012/01/'>January 2012</a>&nbsp;(7)</li> <li><a href='https://herbsutter.com/2011/12/'>December 2011</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2011/11/'>November 2011</a>&nbsp;(6)</li> <li><a href='https://herbsutter.com/2011/10/'>October 2011</a>&nbsp;(10)</li> <li><a href='https://herbsutter.com/2011/09/'>September 2011</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2011/08/'>August 2011</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2011/07/'>July 2011</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2011/06/'>June 2011</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2011/05/'>May 2011</a>&nbsp;(5)</li> <li><a href='https://herbsutter.com/2011/04/'>April 2011</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2011/03/'>March 2011</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2011/01/'>January 2011</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2010/12/'>December 2010</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2010/10/'>October 2010</a>&nbsp;(5)</li> <li><a href='https://herbsutter.com/2010/09/'>September 2010</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2010/08/'>August 2010</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2010/07/'>July 2010</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2010/06/'>June 2010</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2010/05/'>May 2010</a>&nbsp;(5)</li> <li><a href='https://herbsutter.com/2010/04/'>April 2010</a>&nbsp;(5)</li> <li><a href='https://herbsutter.com/2010/03/'>March 2010</a>&nbsp;(9)</li> <li><a href='https://herbsutter.com/2010/02/'>February 2010</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2010/01/'>January 2010</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2009/12/'>December 2009</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2009/11/'>November 2009</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2009/10/'>October 2009</a>&nbsp;(6)</li> <li><a href='https://herbsutter.com/2009/09/'>September 2009</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2009/08/'>August 2009</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2009/07/'>July 2009</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2009/06/'>June 2009</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2009/05/'>May 2009</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2009/04/'>April 2009</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2009/03/'>March 2009</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2009/02/'>February 2009</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2009/01/'>January 2009</a>&nbsp;(5)</li> <li><a href='https://herbsutter.com/2008/12/'>December 2008</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2008/11/'>November 2008</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2008/10/'>October 2008</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2008/09/'>September 2008</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2008/08/'>August 2008</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2008/07/'>July 2008</a>&nbsp;(6)</li> <li><a href='https://herbsutter.com/2008/06/'>June 2008</a>&nbsp;(6)</li> <li><a href='https://herbsutter.com/2008/05/'>May 2008</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2008/04/'>April 2008</a>&nbsp;(6)</li> <li><a href='https://herbsutter.com/2008/03/'>March 2008</a>&nbsp;(5)</li> <li><a href='https://herbsutter.com/2008/02/'>February 2008</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2008/01/'>January 2008</a>&nbsp;(7)</li> <li><a href='https://herbsutter.com/2007/12/'>December 2007</a>&nbsp;(5)</li> <li><a href='https://herbsutter.com/2007/11/'>November 2007</a>&nbsp;(4)</li> <li><a href='https://herbsutter.com/2007/10/'>October 2007</a>&nbsp;(1)</li> <li><a href='https://herbsutter.com/2007/09/'>September 2007</a>&nbsp;(6)</li> <li><a href='https://herbsutter.com/2007/08/'>August 2007</a>&nbsp;(6)</li> <li><a href='https://herbsutter.com/2007/07/'>July 2007</a>&nbsp;(6)</li> <li><a href='https://herbsutter.com/2007/06/'>June 2007</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2007/05/'>May 2007</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2007/04/'>April 2007</a>&nbsp;(2)</li> <li><a href='https://herbsutter.com/2007/03/'>March 2007</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2007/02/'>February 2007</a>&nbsp;(3)</li> <li><a href='https://herbsutter.com/2007/01/'>January 2007</a>&nbsp;(6)</li> <li><a href='https://herbsutter.com/2006/12/'>December 2006</a>&nbsp;(2)</li> </ul> </aside></div><!-- #secondary --> </div><!-- #content --> <footer id="colophon" class="site-footer" role="contentinfo"> <div class="site-info"> <a href="https://wordpress.com/?ref=footer_blog" rel="nofollow">Blog at WordPress.com.</a> </div><!-- .site-info --> </footer><!-- #colophon --> </div><!-- #content-wrapper --> </div><!-- #page --> <script type="text/javascript"> var infiniteScroll = {"settings":{"id":"main","ajaxurl":"https:\/\/herbsutter.com\/?infinity=scrolling","type":"scroll","wrapper":true,"wrapper_class":"infinite-wrap","footer":"page","click_handle":"1","text":"Older posts","totop":"Scroll back to top","currentday":"24.05.13","order":"DESC","scripts":[],"styles":[],"google_analytics":false,"offset":1,"history":{"host":"herbsutter.com","path":"\/2013\/05\/page\/%d\/","use_trailing_slashes":true,"parameters":""},"query_args":{"year":2013,"monthnum":5,"error":"","m":"","p":0,"post_parent":"","subpost":"","subpost_id":"","attachment":"","attachment_id":0,"name":"","pagename":"","page_id":0,"second":"","minute":"","hour":"","day":0,"w":0,"category_name":"","tag":"","cat":"","tag_id":"","author":"","author_name":"","feed":"","tb":"","paged":0,"meta_key":"","meta_value":"","preview":"","s":"","sentence":"","title":"","fields":"","menu_order":"","embed":"","category__in":[],"category__not_in":[],"category__and":[],"post__in":[],"post__not_in":[],"post_name__in":[],"tag__in":[],"tag__not_in":[],"tag__and":[],"tag_slug__in":[],"tag_slug__and":[],"post_parent__in":[],"post_parent__not_in":[],"author__in":[],"author__not_in":[],"search_columns":[],"lazy_load_term_meta":false,"posts_per_page":10,"ignore_sticky_posts":false,"suppress_filters":false,"cache_results":true,"update_post_term_cache":true,"update_menu_item_cache":false,"update_post_meta_cache":true,"post_type":"","nopaging":false,"comments_per_page":"50","no_found_rows":false,"order":"DESC"},"query_before":"2025-02-25 17:57:06","last_post_date":"2013-05-24 07:40:37","body_class":"infinite-scroll neverending","loading_text":"Loading new page","stats":"blog=3379246&v=wpcom&tz=-8&user_id=0&subd=herbsutter&x_pagetype=infinite"}}; </script> <!-- --> <script type="text/javascript" src="//0.gravatar.com/js/hovercards/hovercards.min.js?ver=2025097d8bf6c02970a26c6b0c26b0fcfc89796aa30f84307cffd8fd28d2bcca53dd7a" id="grofiles-cards-js"></script> <script type="text/javascript" id="wpgroho-js-extra"> /* <![CDATA[ */ var WPGroHo = {"my_hash":""}; /* ]]> */ </script> <script crossorigin='anonymous' type='text/javascript' src='https://s2.wp.com/wp-content/mu-plugins/gravatar-hovercards/wpgroho.js?m=1610363240i'></script> <script> // Initialize and attach hovercards to all gravatars ( function() { function init() { if ( typeof Gravatar === 'undefined' ) { return; } if ( typeof Gravatar.init !== 'function' ) { return; } Gravatar.profile_cb = function ( hash, id ) { WPGroHo.syncProfileData( hash, id ); }; Gravatar.my_hash = WPGroHo.my_hash; Gravatar.init( 'body', '#wp-admin-bar-my-account', { i18n: { 'Edit your profile →': 'Edit your profile →', 'View profile →': 'View profile →', 'Contact': 'Contact', 'Send money': 'Send money', 'Sorry, we are unable to load this Gravatar profile.': 'Sorry, we are unable to load this Gravatar profile.', 'Profile not found.': 'Profile not found.', 'Too Many Requests.': 'Too Many Requests.', 'Internal Server Error.': 'Internal Server Error.', }, } ); } if ( document.readyState !== 'loading' ) { init(); } else { document.addEventListener( 'DOMContentLoaded', init ); } } )(); </script> <div style="display:none"> <div class="grofile-hash-map-c0ba56bfd231f8f04feb057728975181"> </div> </div> <div id="infinite-footer"> <div class="container"> <div class="blog-info"> <a id="infinity-blog-title" href="https://herbsutter.com/" rel="home"> Sutter’s Mill </a> </div> <div class="blog-credits"> <a href="https://wordpress.com/?ref=footer_blog" rel="nofollow">Blog at WordPress.com.</a> </div> </div> </div><!-- #infinite-footer --> <div id="actionbar" dir="ltr" style="display: none;" class="actnbr-pub-independent-publisher-2 actnbr-has-follow actnbr-has-actions"> <ul> <li class="actnbr-btn actnbr-hidden"> <a class="actnbr-action actnbr-actn-follow " href=""> <svg class="gridicon" height="20" width="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path clip-rule="evenodd" d="m4 4.5h12v6.5h1.5v-6.5-1.5h-1.5-12-1.5v1.5 10.5c0 1.1046.89543 2 2 2h7v-1.5h-7c-.27614 0-.5-.2239-.5-.5zm10.5 2h-9v1.5h9zm-5 3h-4v1.5h4zm3.5 1.5h-1v1h1zm-1-1.5h-1.5v1.5 1 1.5h1.5 1 1.5v-1.5-1-1.5h-1.5zm-2.5 2.5h-4v1.5h4zm6.5 1.25h1.5v2.25h2.25v1.5h-2.25v2.25h-1.5v-2.25h-2.25v-1.5h2.25z" fill-rule="evenodd"></path></svg> <span>Subscribe</span> </a> <a class="actnbr-action actnbr-actn-following no-display" href=""> <svg class="gridicon" height="20" width="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" clip-rule="evenodd" d="M16 4.5H4V15C4 15.2761 4.22386 15.5 4.5 15.5H11.5V17H4.5C3.39543 17 2.5 16.1046 2.5 15V4.5V3H4H16H17.5V4.5V12.5H16V4.5ZM5.5 6.5H14.5V8H5.5V6.5ZM5.5 9.5H9.5V11H5.5V9.5ZM12 11H13V12H12V11ZM10.5 9.5H12H13H14.5V11V12V13.5H13H12H10.5V12V11V9.5ZM5.5 12H9.5V13.5H5.5V12Z" fill="#008A20"></path><path class="following-icon-tick" d="M13.5 16L15.5 18L19 14.5" stroke="#008A20" stroke-width="1.5"></path></svg> <span>Subscribed</span> </a> <div class="actnbr-popover tip tip-top-left actnbr-notice" id="follow-bubble"> <div class="tip-arrow"></div> <div class="tip-inner actnbr-follow-bubble"> <ul> <li class="actnbr-sitename"> <a href="https://herbsutter.com"> <img loading='lazy' alt='' src='https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=50&#038;d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png' srcset='https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=50&#038;d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 1x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=75&#038;d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 1.5x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=100&#038;d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 2x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=150&#038;d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 3x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=200&#038;d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 4x' class='avatar avatar-50' height='50' width='50' /> Sutter’s Mill </a> </li> <div class="actnbr-message no-display"></div> <form method="post" action="https://subscribe.wordpress.com" accept-charset="utf-8" style="display: none;"> <div class="actnbr-follow-count">Join 5,292 other subscribers</div> <div> <input type="email" name="email" placeholder="Enter your email address" class="actnbr-email-field" aria-label="Enter your email address" /> </div> <input type="hidden" name="action" value="subscribe" /> <input type="hidden" name="blog_id" value="3379246" /> <input type="hidden" name="source" value="https://herbsutter.com/2013/05/" /> <input type="hidden" name="sub-type" value="actionbar-follow" /> <input type="hidden" id="_wpnonce" name="_wpnonce" value="c1038c5b8c" /> <div class="actnbr-button-wrap"> <button type="submit" value="Sign me up"> Sign me up </button> </div> </form> <li class="actnbr-login-nudge"> <div> Already have a WordPress.com account? <a href="https://wordpress.com/log-in?redirect_to=https%3A%2F%2Fr-login.wordpress.com%2Fremote-login.php%3Faction%3Dlink%26back%3Dhttps%253A%252F%252Fherbsutter.com%252F2013%252F05%252F30%252Fgotw-91-smart-pointer-parameters%252F">Log in now.</a> </div> </li> </ul> </div> </div> </li> <li class="actnbr-ellipsis actnbr-hidden"> <svg class="gridicon gridicons-ellipsis" height="24" width="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><path d="M7 12c0 1.104-.896 2-2 2s-2-.896-2-2 .896-2 2-2 2 .896 2 2zm12-2c-1.104 0-2 .896-2 2s.896 2 2 2 2-.896 2-2-.896-2-2-2zm-7 0c-1.104 0-2 .896-2 2s.896 2 2 2 2-.896 2-2-.896-2-2-2z"/></g></svg> <div class="actnbr-popover tip tip-top-left actnbr-more"> <div class="tip-arrow"></div> <div class="tip-inner"> <ul> <li class="actnbr-sitename"> <a href="https://herbsutter.com"> <img loading='lazy' alt='' src='https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=50&#038;d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png' srcset='https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=50&#038;d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 1x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=75&#038;d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 1.5x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=100&#038;d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 2x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=150&#038;d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 3x, https://secure.gravatar.com/blavatar/fe7f5b0b83dba894afe26c42bcab33fe2d1246d9730ef182c72c0bff0dc26acb?s=200&#038;d=https%3A%2F%2Fs2.wp.com%2Fi%2Flogo%2Fwpcom-gray-white.png 4x' class='avatar avatar-50' height='50' width='50' /> Sutter’s Mill </a> </li> <li class="actnbr-folded-follow"> <a class="actnbr-action actnbr-actn-follow " href=""> <svg class="gridicon" height="20" width="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path clip-rule="evenodd" d="m4 4.5h12v6.5h1.5v-6.5-1.5h-1.5-12-1.5v1.5 10.5c0 1.1046.89543 2 2 2h7v-1.5h-7c-.27614 0-.5-.2239-.5-.5zm10.5 2h-9v1.5h9zm-5 3h-4v1.5h4zm3.5 1.5h-1v1h1zm-1-1.5h-1.5v1.5 1 1.5h1.5 1 1.5v-1.5-1-1.5h-1.5zm-2.5 2.5h-4v1.5h4zm6.5 1.25h1.5v2.25h2.25v1.5h-2.25v2.25h-1.5v-2.25h-2.25v-1.5h2.25z" fill-rule="evenodd"></path></svg> <span>Subscribe</span> </a> <a class="actnbr-action actnbr-actn-following no-display" href=""> <svg class="gridicon" height="20" width="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" clip-rule="evenodd" d="M16 4.5H4V15C4 15.2761 4.22386 15.5 4.5 15.5H11.5V17H4.5C3.39543 17 2.5 16.1046 2.5 15V4.5V3H4H16H17.5V4.5V12.5H16V4.5ZM5.5 6.5H14.5V8H5.5V6.5ZM5.5 9.5H9.5V11H5.5V9.5ZM12 11H13V12H12V11ZM10.5 9.5H12H13H14.5V11V12V13.5H13H12H10.5V12V11V9.5ZM5.5 12H9.5V13.5H5.5V12Z" fill="#008A20"></path><path class="following-icon-tick" d="M13.5 16L15.5 18L19 14.5" stroke="#008A20" stroke-width="1.5"></path></svg> <span>Subscribed</span> </a> </li> <li class="actnbr-signup"><a href="https://wordpress.com/start/">Sign up</a></li> <li class="actnbr-login"><a href="https://wordpress.com/log-in?redirect_to=https%3A%2F%2Fr-login.wordpress.com%2Fremote-login.php%3Faction%3Dlink%26back%3Dhttps%253A%252F%252Fherbsutter.com%252F2013%252F05%252F30%252Fgotw-91-smart-pointer-parameters%252F">Log in</a></li> <li class="flb-report"> <a href="https://wordpress.com/abuse/?report_url=https://herbsutter.com" target="_blank" rel="noopener noreferrer"> Report this content </a> </li> <li class="actnbr-reader"> <a href="https://wordpress.com/reader/feeds/171936"> View site in Reader </a> </li> <li class="actnbr-subs"> <a href="https://subscribe.wordpress.com/">Manage subscriptions</a> </li> <li class="actnbr-fold"><a href="">Collapse this bar</a></li> </ul> </div> </div> </li> </ul> </div> <script> window.addEventListener( "load", function( event ) { var link = document.createElement( "link" ); link.href = "https://s0.wp.com/wp-content/mu-plugins/actionbar/actionbar.css?v=20250116"; link.type = "text/css"; link.rel = "stylesheet"; document.head.appendChild( link ); var script = document.createElement( "script" ); script.src = "https://s0.wp.com/wp-content/mu-plugins/actionbar/actionbar.js?v=20250204"; script.defer = true; document.body.appendChild( script ); } ); </script> <div id="jp-carousel-loading-overlay"> <div id="jp-carousel-loading-wrapper"> <span id="jp-carousel-library-loading">&nbsp;</span> </div> </div> <div class="jp-carousel-overlay" style="display: none;"> <div class="jp-carousel-container"> <!-- The Carousel Swiper --> <div class="jp-carousel-wrap swiper-container jp-carousel-swiper-container jp-carousel-transitions" itemscope itemtype="https://schema.org/ImageGallery"> <div class="jp-carousel swiper-wrapper"></div> <div class="jp-swiper-button-prev swiper-button-prev"> <svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <mask id="maskPrev" mask-type="alpha" maskUnits="userSpaceOnUse" x="8" y="6" width="9" height="12"> <path d="M16.2072 16.59L11.6496 12L16.2072 7.41L14.8041 6L8.8335 12L14.8041 18L16.2072 16.59Z" fill="white"/> </mask> <g mask="url(#maskPrev)"> <rect x="0.579102" width="23.8823" height="24" fill="#FFFFFF"/> </g> </svg> </div> <div class="jp-swiper-button-next swiper-button-next"> <svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <mask id="maskNext" mask-type="alpha" maskUnits="userSpaceOnUse" x="8" y="6" width="8" height="12"> <path d="M8.59814 16.59L13.1557 12L8.59814 7.41L10.0012 6L15.9718 12L10.0012 18L8.59814 16.59Z" fill="white"/> </mask> <g mask="url(#maskNext)"> <rect x="0.34375" width="23.8822" height="24" fill="#FFFFFF"/> </g> </svg> </div> </div> <!-- The main close buton --> <div class="jp-carousel-close-hint"> <svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <mask id="maskClose" mask-type="alpha" maskUnits="userSpaceOnUse" x="5" y="5" width="15" height="14"> <path d="M19.3166 6.41L17.9135 5L12.3509 10.59L6.78834 5L5.38525 6.41L10.9478 12L5.38525 17.59L6.78834 19L12.3509 13.41L17.9135 19L19.3166 17.59L13.754 12L19.3166 6.41Z" fill="white"/> </mask> <g mask="url(#maskClose)"> <rect x="0.409668" width="23.8823" height="24" fill="#FFFFFF"/> </g> </svg> </div> <!-- Image info, comments and meta --> <div class="jp-carousel-info"> <div class="jp-carousel-info-footer"> <div class="jp-carousel-pagination-container"> <div class="jp-swiper-pagination swiper-pagination"></div> <div class="jp-carousel-pagination"></div> </div> <div class="jp-carousel-photo-title-container"> <h2 class="jp-carousel-photo-caption"></h2> </div> <div class="jp-carousel-photo-icons-container"> <a href="#" class="jp-carousel-icon-btn jp-carousel-icon-info" aria-label="Toggle photo metadata visibility"> <span class="jp-carousel-icon"> <svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <mask id="maskInfo" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="21" height="20"> <path fill-rule="evenodd" clip-rule="evenodd" d="M12.7537 2C7.26076 2 2.80273 6.48 2.80273 12C2.80273 17.52 7.26076 22 12.7537 22C18.2466 22 22.7046 17.52 22.7046 12C22.7046 6.48 18.2466 2 12.7537 2ZM11.7586 7V9H13.7488V7H11.7586ZM11.7586 11V17H13.7488V11H11.7586ZM4.79292 12C4.79292 16.41 8.36531 20 12.7537 20C17.142 20 20.7144 16.41 20.7144 12C20.7144 7.59 17.142 4 12.7537 4C8.36531 4 4.79292 7.59 4.79292 12Z" fill="white"/> </mask> <g mask="url(#maskInfo)"> <rect x="0.8125" width="23.8823" height="24" fill="#FFFFFF"/> </g> </svg> </span> </a> <a href="#" class="jp-carousel-icon-btn jp-carousel-icon-comments" aria-label="Toggle photo comments visibility"> <span class="jp-carousel-icon"> <svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <mask id="maskComments" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="21" height="20"> <path fill-rule="evenodd" clip-rule="evenodd" d="M4.3271 2H20.2486C21.3432 2 22.2388 2.9 22.2388 4V16C22.2388 17.1 21.3432 18 20.2486 18H6.31729L2.33691 22V4C2.33691 2.9 3.2325 2 4.3271 2ZM6.31729 16H20.2486V4H4.3271V18L6.31729 16Z" fill="white"/> </mask> <g mask="url(#maskComments)"> <rect x="0.34668" width="23.8823" height="24" fill="#FFFFFF"/> </g> </svg> <span class="jp-carousel-has-comments-indicator" aria-label="This image has comments."></span> </span> </a> </div> </div> <div class="jp-carousel-info-extra"> <div class="jp-carousel-info-content-wrapper"> <div class="jp-carousel-photo-title-container"> <h2 class="jp-carousel-photo-title"></h2> </div> <div class="jp-carousel-comments-wrapper"> <div id="jp-carousel-comments-loading"> <span>Loading Comments...</span> </div> <div class="jp-carousel-comments"></div> <div id="jp-carousel-comment-form-container"> <span id="jp-carousel-comment-form-spinner">&nbsp;</span> <div id="jp-carousel-comment-post-results"></div> <form id="jp-carousel-comment-form"> <label for="jp-carousel-comment-form-comment-field" class="screen-reader-text">Write a Comment...</label> <textarea name="comment" class="jp-carousel-comment-form-field jp-carousel-comment-form-textarea" id="jp-carousel-comment-form-comment-field" placeholder="Write a Comment..." ></textarea> <div id="jp-carousel-comment-form-submit-and-info-wrapper"> <div id="jp-carousel-comment-form-commenting-as"> <fieldset> <label for="jp-carousel-comment-form-email-field">Email (Required)</label> <input type="text" name="email" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-email-field" /> </fieldset> <fieldset> <label for="jp-carousel-comment-form-author-field">Name (Required)</label> <input type="text" name="author" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-author-field" /> </fieldset> <fieldset> <label for="jp-carousel-comment-form-url-field">Website</label> <input type="text" name="url" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-url-field" /> </fieldset> </div> <input type="submit" name="submit" class="jp-carousel-comment-form-button" id="jp-carousel-comment-form-button-submit" value="Post Comment" /> </div> </form> </div> </div> <div class="jp-carousel-image-meta"> <div class="jp-carousel-title-and-caption"> <div class="jp-carousel-photo-info"> <h3 class="jp-carousel-caption" itemprop="caption description"></h3> </div> <div class="jp-carousel-photo-description"></div> </div> <ul class="jp-carousel-image-exif" style="display: none;"></ul> <a class="jp-carousel-image-download" href="#" target="_blank" style="display: none;"> <svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="3" y="3" width="19" height="18"> <path fill-rule="evenodd" clip-rule="evenodd" d="M5.84615 5V19H19.7775V12H21.7677V19C21.7677 20.1 20.8721 21 19.7775 21H5.84615C4.74159 21 3.85596 20.1 3.85596 19V5C3.85596 3.9 4.74159 3 5.84615 3H12.8118V5H5.84615ZM14.802 5V3H21.7677V10H19.7775V6.41L9.99569 16.24L8.59261 14.83L18.3744 5H14.802Z" fill="white"/> </mask> <g mask="url(#mask0)"> <rect x="0.870605" width="23.8823" height="24" fill="#FFFFFF"/> </g> </svg> <span class="jp-carousel-download-text"></span> </a> <div class="jp-carousel-image-map" style="display: none;"></div> </div> </div> </div> </div> </div> </div> <link crossorigin='anonymous' rel='stylesheet' id='all-css-0-2' href='https://s2.wp.com/_static/??-eJydzEEKwyAQheEL1Q5JocFFyFmsDkEzjuI4hNy+FJptFln+j8cHezW+cEfukNVU0jWyQMJend/+DaIMuQQlFPCuFRUkkD1WbOajHAifXuQB97Hzcw43vR4Jg1kdEbbjqn7+kufhbUc7vYZxSl9CS2RI&cssminify=yes' type='text/css' media='all' /> <script type="text/javascript" src="https://s1.wp.com/wp-content/js/mobile-useragent-info.js?m=1609849039i&amp;ver=20241018" id="mobile-useragent-info-js" defer="defer" data-wp-strategy="defer"></script> <script type="text/javascript" id="jetpack-carousel-js-extra"> /* <![CDATA[ */ var jetpackSwiperLibraryPath = {"url":"https:\/\/s2.wp.com\/wp-content\/mu-plugins\/jetpack-plugin\/sun\/_inc\/build\/carousel\/swiper-bundle.min.js"}; var jetpackCarouselStrings = {"widths":[370,700,1000,1200,1400,2000],"is_logged_in":"","lang":"en","ajaxurl":"https:\/\/herbsutter.com\/wp-admin\/admin-ajax.php","nonce":"f0f077c76f","display_exif":"1","display_comments":"1","single_image_gallery":"1","single_image_gallery_media_file":"","background_color":"black","comment":"Comment","post_comment":"Post Comment","write_comment":"Write a Comment...","loading_comments":"Loading Comments...","image_label":"Open image in full-screen.","download_original":"View full size <span class=\"photo-size\">{0}<span class=\"photo-size-times\">\u00d7<\/span>{1}<\/span>","no_comment_text":"Please be sure to submit some text with your comment.","no_comment_email":"Please provide an email address to comment.","no_comment_author":"Please provide your name to comment.","comment_post_error":"Sorry, but there was an error posting your comment. Please try again later.","comment_approved":"Your comment was approved.","comment_unapproved":"Your comment is in moderation.","camera":"Camera","aperture":"Aperture","shutter_speed":"Shutter Speed","focal_length":"Focal Length","copyright":"Copyright","comment_registration":"0","require_name_email":"1","login_url":"https:\/\/herbsutter.wordpress.com\/wp-login.php?redirect_to=https%3A%2F%2Fherbsutter.com%2F2013%2F05%2F24%2Fgotw-6a-const-correctness-part-1-3%2F","blog_id":"3379246","meta_data":["camera","aperture","shutter_speed","focal_length","copyright"],"stats_query_args":"blog=3379246&v=wpcom&tz=-8&user_id=0&subd=herbsutter","is_public":"1"}; /* ]]> */ </script> <script type="text/javascript" id="custom-content-types-data-js-before"> /* <![CDATA[ */ var CUSTOM_CONTENT_TYPE__INITIAL_STATE; typeof CUSTOM_CONTENT_TYPE__INITIAL_STATE === "object" || (CUSTOM_CONTENT_TYPE__INITIAL_STATE = JSON.parse(decodeURIComponent("%7B%22active%22%3Atrue%2C%22over_ride%22%3Afalse%2C%22should_show_testimonials%22%3Atrue%2C%22should_show_portfolios%22%3Atrue%7D"))); /* ]]> */ </script> <script crossorigin='anonymous' type='text/javascript' src='https://s0.wp.com/_static/??-eJydkFELgkAQhP9Q22Ji0UP0U0LPVVfv9g73LuvfZ6ARPYUvC98yMzCDUwDjJZJEdAmCTS2LYk8xlGZYGDUJ3lgMVoltjSwNC0cCNaO3duXn3rHse93hV2jsyJFiSNUsqynQfCTCzJa1oxEO2CtKeee2jOw3+nXgAJZlgMabpNDwY0PQu+FciUOEKRjvfiP+HsiUo09K9iNbH8tCV3fJTnl+zo5FXvQvgUiQ1A=='></script> <script type="text/javascript" crossorigin='anonymous' src="https://s0.wp.com/wp-content/mu-plugins/jetpack-plugin/sun/_inc/build/tiled-gallery/tiled-gallery/tiled-gallery.min.js?m=1685112397i&amp;ver=14.4-a.8" id="tiled-gallery-js" defer="defer" data-wp-strategy="defer"></script> <script crossorigin='anonymous' type='text/javascript' src='https://s0.wp.com/wp-content/mu-plugins/carousel-wpcom/carousel-wpcom.js?m=1620989527i'></script> <script type="text/javascript"> (function () { var wpcom_reblog = { source: 'toolbar', toggle_reblog_box_flair: function (obj_id, post_id) { // Go to site selector. This will redirect to their blog if they only have one. const postEndpoint = `https://wordpress.com/post`; // Ideally we would use the permalink here, but fortunately this will be replaced with the // post permalink in the editor. const originalURL = `${ document.location.href }?page_id=${ post_id }`; const url = postEndpoint + '?url=' + encodeURIComponent( originalURL ) + '&is_post_share=true' + '&v=5'; const redirect = function () { if ( ! window.open( url, '_blank' ) ) { location.href = url; } }; if ( /Firefox/.test( navigator.userAgent ) ) { setTimeout( redirect, 0 ); } else { redirect(); } }, }; window.wpcom_reblog = wpcom_reblog; })(); </script> <script type="text/javascript"> (function() { var extend = function(out) { out = out || {}; for (var i = 1; i < arguments.length; i++) { if (!arguments[i]) continue; for (var key in arguments[i]) { if (arguments[i].hasOwnProperty(key)) out[key] = arguments[i][key]; } } return out; }; extend( window.infiniteScroll.settings.scripts, ["jquery-core","jquery-migrate","jquery","jquery.wpcom-proxy-request","jetpack-mu-wpcom-settings","rlt-proxy","wpcom-actionbar-placeholder","grofiles-cards","wpgroho","mobile-useragent-info","custom-content-types-data","the-neverending-homepage","independent-publisher-2-navigation","independent-publisher-2-skip-link-focus-fix","independent-publisher-2-wpcom-functions","jetpack-carousel","tiled-gallery","carousel-wpcom"] ); extend( window.infiniteScroll.settings.styles, ["the-neverending-homepage","wp-block-library","wp-block-library-theme","jetpack-layout-grid","jetpack-ratings","mediaelement","wp-mediaelement","coblocks-frontend","wpcom-core-compat-playlist-styles","wpcom-bbpress2-staff-css","genericons","independent-publisher-2-style","independent-publisher-2-block-style","independent-publisher-2-wpcom-style","reblogging","geo-location-flair","a8c-global-print","h4-global","wp-emoji-styles","videopress-video-style","jetpack-sharing-buttons-style","classic-theme-styles","global-styles","akismet-widget-style","jetpack-global-styles-frontend-style","jetpack-carousel-swiper-css","jetpack-carousel","tiled-gallery","core-block-supports-duotone"] ); })(); </script> <span id="infinite-aria" aria-live="polite"></span> <script src="//stats.wp.com/w.js?68" defer></script> <script type="text/javascript"> _tkq = window._tkq || []; _stq = window._stq || []; _tkq.push(['storeContext', {'blog_id':'3379246','blog_tz':'-8','user_lang':'en','blog_lang':'en','user_id':'0'}]); _stq.push(['view', {'blog':'3379246','v':'wpcom','tz':'-8','user_id':'0','subd':'herbsutter'}]); _stq.push(['extra', {'crypt':'UE40eW5QN0p8M2Y/RE1mNzc2NTVTamdsd0xoLz9RQkM2K298TXY9bERQMXc2MjhEaVZfb2wwakRoSj0mUkp1THptM1NdbkV1WjZIcU9mVWQmPUIvMlN6Jk8wW3NYVEJ3dWZOWExuWD9CbmxqLENKeHZKRG9sOWtMPXxsPzZaPWE9UDdDckNaeEFMRTd6X01ITlUsWnlbaT9+ZDF4Y1MzK3VMNVJEdHppaXVrfjhBRFRfXTcsV21abXlxYTY4aTNUJXJvLT1zLm43JUVJL3wwMmM2WlAxflhER1toZ1N6fEtSWzRuU3UuLCZmWWFiZDBidkF+dV1Na2Y4YTFMJlomcG1kJWhqeV9nZ1d+SVNKdT1xeGUlLWFoVVVyXWYuMVpRQlU0dGZVV0J+ZytRREllTEpSMk0vVGNkdA=='}]); _stq.push([ 'clickTrackerInit', '3379246', '0' ]); </script> <noscript><img src="https://pixel.wp.com/b.gif?v=noscript" style="height:1px;width:1px;overflow:hidden;position:absolute;bottom:1px;" alt="" /></noscript> <script defer id="bilmur" data-customproperties="{&quot;enq_jquery&quot;:&quot;1&quot;,&quot;logged_in&quot;:&quot;0&quot;,&quot;wptheme&quot;:&quot;pub\/independent-publisher-2&quot;,&quot;wptheme_is_block&quot;:&quot;0&quot;}" data-provider="wordpress.com" data-service="simple" data-site-tz="Etc/GMT+8" src="/wp-content/js/bilmur-4.min.js?i=12&m=202509"></script><script> ( function() { function getMobileUserAgentInfo() { if ( typeof wpcom_mobile_user_agent_info === 'object' ) { wpcom_mobile_user_agent_info.init(); var mobileStatsQueryString = ''; if ( wpcom_mobile_user_agent_info.matchedPlatformName !== false ) { mobileStatsQueryString += '&x_' + 'mobile_platforms' + '=' + wpcom_mobile_user_agent_info.matchedPlatformName; } if ( wpcom_mobile_user_agent_info.matchedUserAgentName !== false ) { mobileStatsQueryString += '&x_' + 'mobile_devices' + '=' + wpcom_mobile_user_agent_info.matchedUserAgentName; } if ( wpcom_mobile_user_agent_info.isIPad() ) { mobileStatsQueryString += '&x_' + 'ipad_views' + '=' + 'views'; } if ( mobileStatsQueryString != '' ) { new Image().src = document.location.protocol + '//pixel.wp.com/g.gif?v=wpcom-no-pv' + mobileStatsQueryString + '&baba=' + Math.random(); } } } document.addEventListener( 'DOMContentLoaded', getMobileUserAgentInfo ); } )(); </script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10