11308 lines
345 KiB
HTML
11308 lines
345 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="generator" content="Asciidoctor 1.5.8">
|
|
<meta name="author" content="Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes">
|
|
<title>Boost.SmartPtr: The Smart Pointer Library</title>
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
|
|
<style>
|
|
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
|
|
/* Uncomment @import statement below to use as custom stylesheet */
|
|
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
|
|
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
|
|
audio,canvas,video{display:inline-block}
|
|
audio:not([controls]){display:none;height:0}
|
|
script{display:none!important}
|
|
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
|
|
a{background:transparent}
|
|
a:focus{outline:thin dotted}
|
|
a:active,a:hover{outline:0}
|
|
h1{font-size:2em;margin:.67em 0}
|
|
abbr[title]{border-bottom:1px dotted}
|
|
b,strong{font-weight:bold}
|
|
dfn{font-style:italic}
|
|
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
|
|
mark{background:#ff0;color:#000}
|
|
code,kbd,pre,samp{font-family:monospace;font-size:1em}
|
|
pre{white-space:pre-wrap}
|
|
q{quotes:"\201C" "\201D" "\2018" "\2019"}
|
|
small{font-size:80%}
|
|
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
|
|
sup{top:-.5em}
|
|
sub{bottom:-.25em}
|
|
img{border:0}
|
|
svg:not(:root){overflow:hidden}
|
|
figure{margin:0}
|
|
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
|
|
legend{border:0;padding:0}
|
|
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
|
|
button,input{line-height:normal}
|
|
button,select{text-transform:none}
|
|
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
|
|
button[disabled],html input[disabled]{cursor:default}
|
|
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
|
|
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
|
|
textarea{overflow:auto;vertical-align:top}
|
|
table{border-collapse:collapse;border-spacing:0}
|
|
*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
|
html,body{font-size:100%}
|
|
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
|
|
a:hover{cursor:pointer}
|
|
img,object,embed{max-width:100%;height:auto}
|
|
object,embed{height:100%}
|
|
img{-ms-interpolation-mode:bicubic}
|
|
.left{float:left!important}
|
|
.right{float:right!important}
|
|
.text-left{text-align:left!important}
|
|
.text-right{text-align:right!important}
|
|
.text-center{text-align:center!important}
|
|
.text-justify{text-align:justify!important}
|
|
.hide{display:none}
|
|
img,object,svg{display:inline-block;vertical-align:middle}
|
|
textarea{height:auto;min-height:50px}
|
|
select{width:100%}
|
|
.center{margin-left:auto;margin-right:auto}
|
|
.stretch{width:100%}
|
|
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
|
|
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
|
|
a{color:#2156a5;text-decoration:underline;line-height:inherit}
|
|
a:hover,a:focus{color:#1d4b8f}
|
|
a img{border:none}
|
|
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
|
|
p aside{font-size:.875em;line-height:1.35;font-style:italic}
|
|
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
|
|
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
|
|
h1{font-size:2.125em}
|
|
h2{font-size:1.6875em}
|
|
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
|
|
h4,h5{font-size:1.125em}
|
|
h6{font-size:1em}
|
|
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
|
|
em,i{font-style:italic;line-height:inherit}
|
|
strong,b{font-weight:bold;line-height:inherit}
|
|
small{font-size:60%;line-height:inherit}
|
|
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
|
|
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
|
|
ul,ol{margin-left:1.5em}
|
|
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
|
|
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
|
|
ul.square{list-style-type:square}
|
|
ul.circle{list-style-type:circle}
|
|
ul.disc{list-style-type:disc}
|
|
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
|
|
dl dt{margin-bottom:.3125em;font-weight:bold}
|
|
dl dd{margin-bottom:1.25em}
|
|
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
|
|
abbr{text-transform:none}
|
|
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
|
|
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
|
|
blockquote cite::before{content:"\2014 \0020"}
|
|
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
|
|
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
|
|
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
|
|
h1{font-size:2.75em}
|
|
h2{font-size:2.3125em}
|
|
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
|
|
h4{font-size:1.4375em}}
|
|
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
|
|
table thead,table tfoot{background:#f7f8f7}
|
|
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
|
|
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
|
|
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
|
|
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
|
|
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
|
|
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
|
|
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
|
|
.clearfix::after,.float-group::after{clear:both}
|
|
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}
|
|
*:not(pre)>code.nobreak{word-wrap:normal}
|
|
*:not(pre)>code.nowrap{white-space:nowrap}
|
|
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
|
|
em em{font-style:normal}
|
|
strong strong{font-weight:400}
|
|
.keyseq{color:rgba(51,51,51,.8)}
|
|
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
|
|
.keyseq kbd:first-child{margin-left:0}
|
|
.keyseq kbd:last-child{margin-right:0}
|
|
.menuseq,.menuref{color:#000}
|
|
.menuseq b:not(.caret),.menuref{font-weight:inherit}
|
|
.menuseq{word-spacing:-.02em}
|
|
.menuseq b.caret{font-size:1.25em;line-height:.8}
|
|
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
|
|
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
|
|
b.button::before{content:"[";padding:0 3px 0 2px}
|
|
b.button::after{content:"]";padding:0 2px 0 3px}
|
|
p a>code:hover{color:rgba(0,0,0,.9)}
|
|
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
|
|
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
|
|
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
|
|
#content{margin-top:1.25em}
|
|
#content::before{content:none}
|
|
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
|
|
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
|
|
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
|
|
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
|
|
#header .details span:first-child{margin-left:-.125em}
|
|
#header .details span.email a{color:rgba(0,0,0,.85)}
|
|
#header .details br{display:none}
|
|
#header .details br+span::before{content:"\00a0\2013\00a0"}
|
|
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
|
|
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
|
|
#header #revnumber{text-transform:capitalize}
|
|
#header #revnumber::after{content:"\00a0"}
|
|
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
|
|
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
|
|
#toc>ul{margin-left:.125em}
|
|
#toc ul.sectlevel0>li>a{font-style:italic}
|
|
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
|
|
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
|
|
#toc li{line-height:1.3334;margin-top:.3334em}
|
|
#toc a{text-decoration:none}
|
|
#toc a:active{text-decoration:underline}
|
|
#toctitle{color:#7a2518;font-size:1.2em}
|
|
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
|
|
body.toc2{padding-left:15em;padding-right:0}
|
|
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
|
|
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
|
|
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
|
|
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
|
|
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
|
|
body.toc2.toc-right{padding-left:0;padding-right:15em}
|
|
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
|
|
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
|
|
#toc.toc2{width:20em}
|
|
#toc.toc2 #toctitle{font-size:1.375em}
|
|
#toc.toc2>ul{font-size:.95em}
|
|
#toc.toc2 ul ul{padding-left:1.25em}
|
|
body.toc2.toc-right{padding-left:0;padding-right:20em}}
|
|
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
|
|
#content #toc>:first-child{margin-top:0}
|
|
#content #toc>:last-child{margin-bottom:0}
|
|
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
|
|
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
|
|
#content{margin-bottom:.625em}
|
|
.sect1{padding-bottom:.625em}
|
|
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
|
|
.sect1{padding-bottom:1.25em}}
|
|
.sect1:last-child{padding-bottom:0}
|
|
.sect1+.sect1{border-top:1px solid #e7e7e9}
|
|
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
|
|
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
|
|
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
|
|
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
|
|
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
|
|
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
|
|
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
|
|
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
|
|
.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
|
|
table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit}
|
|
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
|
|
.admonitionblock>table td.icon{text-align:center;width:80px}
|
|
.admonitionblock>table td.icon img{max-width:none}
|
|
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
|
|
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6)}
|
|
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
|
|
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
|
|
.exampleblock>.content>:first-child{margin-top:0}
|
|
.exampleblock>.content>:last-child{margin-bottom:0}
|
|
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
|
|
.sidebarblock>:first-child{margin-top:0}
|
|
.sidebarblock>:last-child{margin-bottom:0}
|
|
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
|
|
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
|
|
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
|
|
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
|
|
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;overflow-x:auto;padding:1em;font-size:.8125em}
|
|
@media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
|
|
@media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
|
|
.literalblock pre.nowrap,.literalblock pre.nowrap pre,.listingblock pre.nowrap,.listingblock pre.nowrap pre{white-space:pre;word-wrap:normal}
|
|
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
|
|
.listingblock pre.highlightjs{padding:0}
|
|
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
|
|
.listingblock pre.prettyprint{border-width:0}
|
|
.listingblock>.content{position:relative}
|
|
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
|
|
.listingblock:hover code[data-lang]::before{display:block}
|
|
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999}
|
|
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
|
|
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
|
|
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
|
|
table.pyhltable td.code{padding-left:.75em;padding-right:0}
|
|
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #dddddf}
|
|
pre.pygments .lineno{display:inline-block;margin-right:.25em}
|
|
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
|
|
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
|
|
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
|
|
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
|
|
.quoteblock blockquote{margin:0;padding:0;border:0}
|
|
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
|
|
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
|
|
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
|
|
.verseblock{margin:0 1em 1.25em}
|
|
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
|
|
.verseblock pre strong{font-weight:400}
|
|
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
|
|
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
|
|
.quoteblock .attribution br,.verseblock .attribution br{display:none}
|
|
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
|
|
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
|
|
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
|
|
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
|
|
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
|
|
.quoteblock.excerpt,.quoteblock .quoteblock{margin:0 0 1.25em;padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
|
|
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
|
|
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;text-align:left;margin-right:0}
|
|
table.tableblock{max-width:100%;border-collapse:separate}
|
|
p.tableblock:last-child{margin-bottom:0}
|
|
td.tableblock>.content{margin-bottom:-1.25em}
|
|
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
|
|
table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}
|
|
table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}
|
|
table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}
|
|
table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px}
|
|
table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0}
|
|
table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}
|
|
table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}
|
|
table.frame-all{border-width:1px}
|
|
table.frame-sides{border-width:0 1px}
|
|
table.frame-topbot,table.frame-ends{border-width:1px 0}
|
|
table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7}
|
|
table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none}
|
|
th.halign-left,td.halign-left{text-align:left}
|
|
th.halign-right,td.halign-right{text-align:right}
|
|
th.halign-center,td.halign-center{text-align:center}
|
|
th.valign-top,td.valign-top{vertical-align:top}
|
|
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
|
|
th.valign-middle,td.valign-middle{vertical-align:middle}
|
|
table thead th,table tfoot th{font-weight:bold}
|
|
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
|
|
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
|
|
p.tableblock>code:only-child{background:none;padding:0}
|
|
p.tableblock{font-size:1em}
|
|
td>div.verse{white-space:pre}
|
|
ol{margin-left:1.75em}
|
|
ul li ol{margin-left:1.5em}
|
|
dl dd{margin-left:1.125em}
|
|
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
|
|
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
|
|
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
|
|
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
|
|
ul.unstyled,ol.unstyled{margin-left:0}
|
|
ul.checklist{margin-left:.625em}
|
|
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
|
|
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}
|
|
ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
|
|
ul.inline>li{margin-left:1.25em}
|
|
.unstyled dl dt{font-weight:400;font-style:normal}
|
|
ol.arabic{list-style-type:decimal}
|
|
ol.decimal{list-style-type:decimal-leading-zero}
|
|
ol.loweralpha{list-style-type:lower-alpha}
|
|
ol.upperalpha{list-style-type:upper-alpha}
|
|
ol.lowerroman{list-style-type:lower-roman}
|
|
ol.upperroman{list-style-type:upper-roman}
|
|
ol.lowergreek{list-style-type:lower-greek}
|
|
.hdlist>table,.colist>table{border:0;background:none}
|
|
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
|
|
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
|
|
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
|
|
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
|
|
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
|
|
.colist td:not([class]):first-child img{max-width:none}
|
|
.colist td:not([class]):last-child{padding:.25em 0}
|
|
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
|
|
.imageblock.left{margin:.25em .625em 1.25em 0}
|
|
.imageblock.right{margin:.25em 0 1.25em .625em}
|
|
.imageblock>.title{margin-bottom:0}
|
|
.imageblock.thumb,.imageblock.th{border-width:6px}
|
|
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
|
|
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
|
|
.image.left{margin-right:.625em}
|
|
.image.right{margin-left:.625em}
|
|
a.image{text-decoration:none;display:inline-block}
|
|
a.image object{pointer-events:none}
|
|
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
|
|
sup.footnote a,sup.footnoteref a{text-decoration:none}
|
|
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
|
|
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
|
|
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
|
|
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
|
|
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
|
|
#footnotes .footnote:last-of-type{margin-bottom:0}
|
|
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
|
|
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
|
|
.gist .file-data>table td.line-data{width:99%}
|
|
div.unbreakable{page-break-inside:avoid}
|
|
.big{font-size:larger}
|
|
.small{font-size:smaller}
|
|
.underline{text-decoration:underline}
|
|
.overline{text-decoration:overline}
|
|
.line-through{text-decoration:line-through}
|
|
.aqua{color:#00bfbf}
|
|
.aqua-background{background-color:#00fafa}
|
|
.black{color:#000}
|
|
.black-background{background-color:#000}
|
|
.blue{color:#0000bf}
|
|
.blue-background{background-color:#0000fa}
|
|
.fuchsia{color:#bf00bf}
|
|
.fuchsia-background{background-color:#fa00fa}
|
|
.gray{color:#606060}
|
|
.gray-background{background-color:#7d7d7d}
|
|
.green{color:#006000}
|
|
.green-background{background-color:#007d00}
|
|
.lime{color:#00bf00}
|
|
.lime-background{background-color:#00fa00}
|
|
.maroon{color:#600000}
|
|
.maroon-background{background-color:#7d0000}
|
|
.navy{color:#000060}
|
|
.navy-background{background-color:#00007d}
|
|
.olive{color:#606000}
|
|
.olive-background{background-color:#7d7d00}
|
|
.purple{color:#600060}
|
|
.purple-background{background-color:#7d007d}
|
|
.red{color:#bf0000}
|
|
.red-background{background-color:#fa0000}
|
|
.silver{color:#909090}
|
|
.silver-background{background-color:#bcbcbc}
|
|
.teal{color:#006060}
|
|
.teal-background{background-color:#007d7d}
|
|
.white{color:#bfbfbf}
|
|
.white-background{background-color:#fafafa}
|
|
.yellow{color:#bfbf00}
|
|
.yellow-background{background-color:#fafa00}
|
|
span.icon>.fa{cursor:default}
|
|
a span.icon>.fa{cursor:inherit}
|
|
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
|
|
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
|
|
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
|
|
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
|
|
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
|
|
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
|
|
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
|
|
.conum[data-value] *{color:#fff!important}
|
|
.conum[data-value]+b{display:none}
|
|
.conum[data-value]::after{content:attr(data-value)}
|
|
pre .conum[data-value]{position:relative;top:-.125em}
|
|
b.conum *{color:inherit!important}
|
|
.conum:not([data-value]):empty{display:none}
|
|
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
|
|
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
|
|
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
|
|
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
|
|
p{margin-bottom:1.25rem}
|
|
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
|
|
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
|
|
.print-only{display:none!important}
|
|
@page{margin:1.25cm .75cm}
|
|
@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
|
|
html{font-size:80%}
|
|
a{color:inherit!important;text-decoration:underline!important}
|
|
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
|
|
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
|
|
abbr[title]::after{content:" (" attr(title) ")"}
|
|
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
|
|
thead{display:table-header-group}
|
|
svg{max-width:100%}
|
|
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
|
|
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
|
|
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
|
|
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
|
|
body.book #header{text-align:center}
|
|
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
|
|
body.book #header .details{border:0!important;display:block;padding:0!important}
|
|
body.book #header .details span:first-child{margin-left:0!important}
|
|
body.book #header .details br{display:block}
|
|
body.book #header .details br+span::before{content:none!important}
|
|
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
|
|
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
|
|
.listingblock code[data-lang]::before{display:block}
|
|
#footer{padding:0 .9375em}
|
|
.hide-on-print{display:none!important}
|
|
.print-only{display:block!important}
|
|
.hide-for-print{display:none!important}
|
|
.show-for-print{display:inherit!important}}
|
|
@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem}
|
|
.sect1{padding:0!important}
|
|
.sect1+.sect1{border:0}
|
|
#footer{background:none}
|
|
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
|
|
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
|
|
</style>
|
|
</head>
|
|
<body class="article toc2 toc-left">
|
|
<div id="header">
|
|
<h1>Boost.SmartPtr: The Smart Pointer Library</h1>
|
|
<div class="details">
|
|
<span id="author" class="author">Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes</span><br>
|
|
</div>
|
|
<div id="toc" class="toc2">
|
|
<div id="toctitle">Table of Contents</div>
|
|
<ul class="sectlevel1">
|
|
<li><a href="#introduction">Introduction</a></li>
|
|
<li><a href="#changelog">Revision History</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#changelog_changes_in_1_74_0">Changes in 1.74.0</a></li>
|
|
<li><a href="#changelog_changes_in_1_72_0">Changes in 1.72.0</a></li>
|
|
<li><a href="#changelog_changes_in_1_71_0">Changes in 1.71.0</a></li>
|
|
<li><a href="#changelog_changes_in_1_65_0">Changes in 1.65.0</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#scoped_ptr">scoped_ptr: Scoped Object Ownership</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#scoped_ptr_description">Description</a></li>
|
|
<li><a href="#scoped_ptr_synopsis">Synopsis</a></li>
|
|
<li><a href="#scoped_ptr_members">Members</a></li>
|
|
<li><a href="#scoped_ptr_free_functions">Free Functions</a></li>
|
|
<li><a href="#scoped_ptr_example">Example</a></li>
|
|
<li><a href="#scoped_ptr_rationale">Rationale</a></li>
|
|
<li><a href="#scoped_ptr_handlebody_idiom">Handle/Body Idiom</a></li>
|
|
<li><a href="#scoped_ptr_frequently_asked_questions">Frequently Asked Questions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#scoped_array">scoped_array: Scoped Array Ownership</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#scoped_array_description">Description</a></li>
|
|
<li><a href="#scoped_array_synopsis">Synopsis</a></li>
|
|
<li><a href="#scoped_array_members">Members</a></li>
|
|
<li><a href="#scoped_array_free_functions">Free Functions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#shared_ptr">shared_ptr: Shared Ownership</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#shared_ptr_description">Description</a></li>
|
|
<li><a href="#shared_ptr_best_practices">Best Practices</a></li>
|
|
<li><a href="#shared_ptr_synopsis">Synopsis</a></li>
|
|
<li><a href="#shared_ptr_members">Members</a></li>
|
|
<li><a href="#shared_ptr_free_functions">Free Functions</a></li>
|
|
<li><a href="#shared_ptr_example">Example</a></li>
|
|
<li><a href="#shared_ptr_handlebody_idiom">Handle/Body Idiom</a></li>
|
|
<li><a href="#shared_ptr_thread_safety">Thread Safety</a></li>
|
|
<li><a href="#shared_ptr_frequently_asked_questions">Frequently Asked Questions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#weak_ptr">weak_ptr: Non-owning Observer</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#weak_ptr_description">Description</a></li>
|
|
<li><a href="#weak_ptr_synopsis">Synopsis</a></li>
|
|
<li><a href="#weak_ptr_members">Members</a></li>
|
|
<li><a href="#weak_ptr_free_functions">Free Functions</a></li>
|
|
<li><a href="#weak_ptr_frequently_asked_questions">Frequently Asked Questions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#make_shared">make_shared: Creating shared_ptr</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#make_shared_description">Description</a></li>
|
|
<li><a href="#make_shared_rationale">Rationale</a></li>
|
|
<li><a href="#make_shared_synopsis">Synopsis</a></li>
|
|
<li><a href="#make_shared_common_requirements">Common Requirements</a></li>
|
|
<li><a href="#make_shared_free_functions">Free Functions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#enable_shared_from_this">enable_shared_from_this</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#enable_shared_from_this_description">Description</a></li>
|
|
<li><a href="#enable_shared_from_this_example">Example</a></li>
|
|
<li><a href="#enable_shared_from_this_synopsis">Synopsis</a></li>
|
|
<li><a href="#enable_shared_from_this_members">Members</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#enable_shared_from">enable_shared_from</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#enable_shared_from_description">Description</a></li>
|
|
<li><a href="#enable_shared_from_example">Example</a></li>
|
|
<li><a href="#enable_shared_from_synopsis">Synopsis</a></li>
|
|
<li><a href="#enable_shared_from_functions">Functions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#make_unique">make_unique: Creating unique_ptr</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#make_unique_description">Description</a></li>
|
|
<li><a href="#make_unique_rationale">Rationale</a></li>
|
|
<li><a href="#make_unique_synopsis">Synopsis</a></li>
|
|
<li><a href="#make_unique_free_functions">Free Functions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#allocate_unique">allocate_unique: Creating unique_ptr</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#allocate_unique_description">Description</a></li>
|
|
<li><a href="#allocate_unique_rationale">Rationale</a></li>
|
|
<li><a href="#allocate_unique_synopsis">Synopsis</a></li>
|
|
<li><a href="#allocate_unique_common_requirements">Common Requirements</a></li>
|
|
<li><a href="#allocate_unique_free_functions">Free Functions</a></li>
|
|
<li><a href="#allocate_unique_deleter">Deleter</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#intrusive_ptr">intrusive_ptr: Managing Objects with Embedded Counts</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#intrusive_ptr_description">Description</a></li>
|
|
<li><a href="#intrusive_ptr_synopsis">Synopsis</a></li>
|
|
<li><a href="#intrusive_ptr_members">Members</a></li>
|
|
<li><a href="#intrusive_ptr_free_functions">Free Functions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#intrusive_ref_counter">intrusive_ref_counter</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#intrusive_ref_counter_description">Description</a></li>
|
|
<li><a href="#intrusive_ref_counter_synopsis">Synopsis</a></li>
|
|
<li><a href="#intrusive_ref_counter_members">Members</a></li>
|
|
<li><a href="#intrusive_ref_counter_free_functions">Free Functions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#local_shared_ptr">local_shared_ptr: Shared Ownership within a Single Thread</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#local_shared_ptr_description">Description</a></li>
|
|
<li><a href="#local_shared_ptr_synopsis">Synopsis</a></li>
|
|
<li><a href="#local_shared_ptr_members">Members</a></li>
|
|
<li><a href="#local_shared_ptr_free_functions">Free Functions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#make_local_shared">make_local_shared: Creating local_shared_ptr</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#make_local_shared_description">Description</a></li>
|
|
<li><a href="#make_local_shared_synopsis">Synopsis</a></li>
|
|
<li><a href="#make_local_shared_description_2">Description</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#pointer_cast">Generic Pointer Casts</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#pointer_cast_description">Description</a></li>
|
|
<li><a href="#pointer_cast_rationale">Rationale</a></li>
|
|
<li><a href="#pointer_cast_synopsis">Synopsis</a></li>
|
|
<li><a href="#pointer_cast_free_functions">Free Functions</a></li>
|
|
<li><a href="#pointer_cast_example">Example</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#pointer_to_other">pointer_to_other</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#pointer_to_other_description">Description</a></li>
|
|
<li><a href="#pointer_to_other_rationale">Rationale</a></li>
|
|
<li><a href="#pointer_to_other_synopsis">Synopsis</a></li>
|
|
<li><a href="#pointer_to_other_example">Example</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#atomic_shared_ptr">atomic_shared_ptr</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#atomic_shared_ptr_description">Description</a></li>
|
|
<li><a href="#atomic_shared_ptr_synopsis">Synopsis</a></li>
|
|
<li><a href="#atomic_shared_ptr_members">Members</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#owner_less">owner_less</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#owner_less_description">Description</a></li>
|
|
<li><a href="#owner_less_synopsis">Synopsis</a></li>
|
|
<li><a href="#owner_less_members">Members</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#owner_equal_to">owner_equal_to</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#owner_equal_to_description">Description</a></li>
|
|
<li><a href="#owner_equal_to_synopsis">Synopsis</a></li>
|
|
<li><a href="#owner_equal_to_members">Members</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#owner_hash">owner_hash</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#owner_hash_to_description">Description</a></li>
|
|
<li><a href="#owner_hash_to_example">Example</a></li>
|
|
<li><a href="#owner_hash_to_synopsis">Synopsis</a></li>
|
|
<li><a href="#owner_hash_to_members">Members</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#techniques">Appendix A: Smart Pointer Programming Techniques</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#techniques_incomplete">Using incomplete classes for implementation hiding</a></li>
|
|
<li><a href="#techniques_the_pimpl_idiom">The "Pimpl" idiom</a></li>
|
|
<li><a href="#techniques_using_abstract_classes_for_implementation_hiding">Using abstract classes for implementation hiding</a></li>
|
|
<li><a href="#techniques_preventing_delete_px_get">Preventing <code>delete px.get()</code></a></li>
|
|
<li><a href="#techniques_encapsulating_allocation_details_wrapping_factory_functions">Encapsulating allocation details, wrapping factory functions</a></li>
|
|
<li><a href="#techniques_static">Using a shared_ptr to hold a pointer to a statically allocated object</a></li>
|
|
<li><a href="#techniques_using_a_shared_ptr_to_hold_a_pointer_to_a_com_object">Using a shared_ptr to hold a pointer to a COM Object</a></li>
|
|
<li><a href="#techniques_intrusive">Using a shared_ptr to hold a pointer to an object with an embedded reference count</a></li>
|
|
<li><a href="#techniques_using_a_shared_ptr_to_hold_another_shared_ownership_smart_pointer">Using a shared_ptr to hold another shared ownership smart pointer</a></li>
|
|
<li><a href="#techniques_from_raw">Obtaining a shared_ptr from a raw pointer</a></li>
|
|
<li><a href="#techniques_obtaining_a_shared_ptr_weak_ptr_to_this_in_a_constructor">Obtaining a shared_ptr (weak_ptr) to this in a constructor</a></li>
|
|
<li><a href="#techniques_obtaining_a_shared_ptr_to_this">Obtaining a shared_ptr to this</a></li>
|
|
<li><a href="#techniques_using_shared_ptr_as_a_smart_counted_handle">Using shared_ptr as a smart counted handle</a></li>
|
|
<li><a href="#techniques_using_shared_ptr_to_execute_code_on_block_exit">Using shared_ptr to execute code on block exit</a></li>
|
|
<li><a href="#techniques_using_shared_ptrvoid_to_hold_an_arbitrary_object">Using shared_ptr<void> to hold an arbitrary object</a></li>
|
|
<li><a href="#techniques_associating_arbitrary_data_with_heterogeneous_shared_ptr_instances">Associating arbitrary data with heterogeneous <code>shared_ptr</code> instances</a></li>
|
|
<li><a href="#techniques_using_shared_ptr_as_a_copyconstructible_mutex_lock">Using <code>shared_ptr</code> as a <code>CopyConstructible</code> mutex lock</a></li>
|
|
<li><a href="#techniques_using_shared_ptr_to_wrap_member_function_calls">Using shared_ptr to wrap member function calls</a></li>
|
|
<li><a href="#techniques_delayed_deallocation">Delayed deallocation</a></li>
|
|
<li><a href="#techniques_weak_without_shared">Weak pointers to objects not managed by a shared_ptr</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#history">Appendix B: History and Acknowledgments</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#history_summer_1994">Summer 1994</a></li>
|
|
<li><a href="#history_october_1998">October 1998</a></li>
|
|
<li><a href="#history_may_1999">May 1999</a></li>
|
|
<li><a href="#history_september_1999">September 1999</a></li>
|
|
<li><a href="#history_november_1999">November 1999</a></li>
|
|
<li><a href="#history_may_2001">May 2001</a></li>
|
|
<li><a href="#history_january_2002">January 2002</a></li>
|
|
<li><a href="#history_march_2003">March 2003</a></li>
|
|
<li><a href="#history_july_2007">July 2007</a></li>
|
|
<li><a href="#history_november_2012">November 2012</a></li>
|
|
<li><a href="#history_april_2013">April 2013</a></li>
|
|
<li><a href="#history_february_2014">February 2014</a></li>
|
|
<li><a href="#history_february_2017">February 2017</a></li>
|
|
<li><a href="#history_june_2017">June 2017</a></li>
|
|
<li><a href="#history_august_2019">August 2019</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#shared_array">Appendix C: shared_array (deprecated)</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#shared_array_description">Description</a></li>
|
|
<li><a href="#shared_array_synopsis">Synopsis</a></li>
|
|
<li><a href="#shared_array_members">Members</a></li>
|
|
<li><a href="#shared_array_free_functions">Free Functions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#copyright">Appendix D: Copyright and License</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div id="content">
|
|
<div class="sect1">
|
|
<h2 id="introduction">Introduction</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>Smart pointers are objects which store pointers to dynamically allocated (heap) objects.
|
|
They behave much like built-in C++ pointers except that they automatically delete the object
|
|
pointed to at the appropriate time. Smart pointers are particularly useful in the face of
|
|
exceptions as they ensure proper destruction of dynamically allocated objects. They can also be
|
|
used to keep track of dynamically allocated objects shared by multiple owners.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Conceptually, smart pointers are seen as owning the object pointed to, and thus responsible for
|
|
deletion of the object when it is no longer needed. As such, they are examples of the "resource
|
|
acquisition is initialization" idiom described in Bjarne Stroustrup’s "The C++ Programming Language",
|
|
3rd edition, Section 14.4, Resource Management.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This library provides six smart pointer class templates:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code><a href="#scoped_ptr">scoped_ptr</a></code>, used to contain ownership of a dynamically allocated object to the current scope;</p>
|
|
</li>
|
|
<li>
|
|
<p><code><a href="#scoped_array">scoped_array</a></code>, which provides scoped ownership for a dynamically allocated array;</p>
|
|
</li>
|
|
<li>
|
|
<p><code><a href="#shared_ptr">shared_ptr</a></code>, a versatile tool for managing shared ownership of an object or array;</p>
|
|
</li>
|
|
<li>
|
|
<p><code><a href="#weak_ptr">weak_ptr</a></code>, a non-owning observer to a <code>shared_ptr</code>-managed object that can be promoted temporarily to <code>shared_ptr</code>;</p>
|
|
</li>
|
|
<li>
|
|
<p><code><a href="#intrusive_ptr">intrusive_ptr</a></code>, a pointer to objects with an embedded reference count;</p>
|
|
</li>
|
|
<li>
|
|
<p><code><a href="#local_shared_ptr">local_shared_ptr</a></code>, providing shared ownership within a single thread.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>shared_ptr</code> and <code>weak_ptr</code> are part of the C++ standard since its 2011 iteration.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In addition, the library contains the following supporting utility functions and classes:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code><a href="#make_shared">make_shared</a></code> and <code>allocate_shared</code>, factory functions for creating objects that return a <code>shared_ptr</code>;</p>
|
|
</li>
|
|
<li>
|
|
<p><code><a href="#make_unique">make_unique</a></code>, a factory function returning <code>std::unique_ptr</code>;</p>
|
|
</li>
|
|
<li>
|
|
<p><code><a href="#allocate_unique">allocate_unique</a></code>, a factory function for creating objects using an allocator that returns a <code>std::unique_ptr</code>;</p>
|
|
</li>
|
|
<li>
|
|
<p><code><a href="#enable_shared_from_this">enable_shared_from_this</a></code>, a helper base class that enables the acquisition of a <code>shared_ptr</code> pointing to <code>this</code>;</p>
|
|
</li>
|
|
<li>
|
|
<p><code><a href="#enable_shared_from">enable_shared_from</a></code>, a newer and better replacement for <code>enable_shared_from_this</code>;</p>
|
|
</li>
|
|
<li>
|
|
<p><code><a href="#pointer_to_other">pointer_to_other</a></code>, a helper trait for converting one smart pointer type to another;</p>
|
|
</li>
|
|
<li>
|
|
<p><code><a href="#pointer_cast">static_pointer_cast</a></code> and companions, generic smart pointer casts;</p>
|
|
</li>
|
|
<li>
|
|
<p><code><a href="#intrusive_ref_counter">intrusive_ref_counter</a></code>, a helper base class containing a reference count.</p>
|
|
</li>
|
|
<li>
|
|
<p><code><a href="#atomic_shared_ptr">atomic_shared_ptr</a></code>, a helper class implementing the interface of <code>std::atomic</code> for a value of type <code>shared_ptr</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As a general rule, the destructor or <code>operator delete</code> for an object managed by pointers in the library
|
|
are not allowed to throw exceptions.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="changelog">Revision History</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="changelog_changes_in_1_74_0">Changes in 1.74.0</h3>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Added <code>owner_equals</code> to <code>shared_ptr</code>, <code>weak_ptr</code>, <code>local_shared_ptr</code></p>
|
|
</li>
|
|
<li>
|
|
<p>Added <code>owner_hash_value</code> to <code>shared_ptr</code>, <code>weak_ptr</code></p>
|
|
</li>
|
|
<li>
|
|
<p>Added <code>owner_equal_to</code>, <code>owner_hash</code></p>
|
|
</li>
|
|
<li>
|
|
<p>Added <code>std::hash</code> specializations for <code>shared_ptr</code>, <code>local_shared_ptr</code></p>
|
|
</li>
|
|
<li>
|
|
<p>Added <code>boost::hash</code> support to, and <code>std::hash</code>, <code>std::equal_to</code>
|
|
specializations for, <code>weak_ptr</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="changelog_changes_in_1_72_0">Changes in 1.72.0</h3>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Added <code>allocate_unique</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="changelog_changes_in_1_71_0">Changes in 1.71.0</h3>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Added aliasing constructors to <code>weak_ptr</code></p>
|
|
</li>
|
|
<li>
|
|
<p>Added <code>weak_ptr<T>::empty()</code></p>
|
|
</li>
|
|
<li>
|
|
<p>Added <code>enable_shared_from</code>, <code>shared_from</code>, and <code>weak_from</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="changelog_changes_in_1_65_0">Changes in 1.65.0</h3>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Added <code>atomic_shared_ptr</code></p>
|
|
</li>
|
|
<li>
|
|
<p>Added <code>local_shared_ptr</code>, <code>make_local_shared</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="scoped_ptr">scoped_ptr: Scoped Object Ownership</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="scoped_ptr_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The <code>scoped_ptr</code> class template stores a pointer to a dynamically allocated object.
|
|
(Dynamically allocated objects are allocated with the C++ <code>new</code> expression.) The
|
|
object pointed to is guaranteed to be deleted, either on destruction of the <code>scoped_ptr</code>,
|
|
or via an explicit <code>reset</code>. See the <a href="#scoped_ptr_example">example</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>scoped_ptr</code> is a simple solution for simple needs. It supplies a basic "resource acquisition
|
|
is initialization" facility, without shared-ownership or transfer-of-ownership semantics.
|
|
Both its name and enforcement of semantics (by being noncopyable) signal its intent to retain
|
|
ownership solely within the current scope. Because it is noncopyable, it is safer than <code>shared_ptr</code>
|
|
for pointers which should not be copied.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Because <code>scoped_ptr</code> is simple, in its usual implementation every operation is as fast as for a
|
|
built-in pointer and it has no more space overhead that a built-in pointer.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>scoped_ptr</code> cannot be used in C++ Standard Library containers. Use <code>shared_ptr</code> or <code>std::unique_ptr</code>
|
|
if you need a smart pointer that can.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>scoped_ptr</code> cannot correctly hold a pointer to a dynamically allocated array. See <code>scoped_array</code> for that usage.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The class template is parameterized on <code>T</code>, the type of the object pointed to. Destroying <code>T</code> must not thow exceptions,
|
|
and <code>T</code> must be complete at the point <code>scoped_ptr<T>::~scoped_ptr</code> is instantiated.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="scoped_ptr_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>scoped_ptr</code> is defined in <code><boost/smart_ptr/scoped_ptr.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
|
|
template<class T> class scoped_ptr {
|
|
private:
|
|
|
|
scoped_ptr(scoped_ptr const&);
|
|
scoped_ptr& operator=(scoped_ptr const&);
|
|
|
|
void operator==(scoped_ptr const&) const;
|
|
void operator!=(scoped_ptr const&) const;
|
|
|
|
public:
|
|
|
|
typedef T element_type;
|
|
|
|
explicit scoped_ptr(T * p = 0) noexcept;
|
|
~scoped_ptr() noexcept;
|
|
|
|
void reset(T * p = 0) noexcept;
|
|
|
|
T & operator*() const noexcept;
|
|
T * operator->() const noexcept;
|
|
T * get() const noexcept;
|
|
|
|
explicit operator bool() const noexcept;
|
|
|
|
void swap(scoped_ptr & b) noexcept;
|
|
};
|
|
|
|
template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) noexcept;
|
|
|
|
template<class T>
|
|
bool operator==( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
|
|
template<class T>
|
|
bool operator==( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
|
|
|
|
template<class T>
|
|
bool operator!=( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
|
|
template<class T>
|
|
bool operator!=( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="scoped_ptr_members">Members</h3>
|
|
<div class="sect3">
|
|
<h4 id="scoped_ptr_element_type">element_type</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>typedef T element_type;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Provides the type of the stored pointer.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_ptr_constructor">constructor</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>explicit scoped_ptr(T * p = 0) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Constructs a <code>scoped_ptr</code>, storing a copy of <code>p</code>, which must have been allocated via a
|
|
C++ <code>new</code> expression or be 0. <code>T</code> is not required be a complete type.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_ptr_destructor">destructor</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>~scoped_ptr() noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Destroys the object pointed to by the stored pointer, if any, as if by using
|
|
<code>delete this->get()</code>. <code>T</code> must be a complete type.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_ptr_reset">reset</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>void reset(T * p = 0) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Deletes the object pointed to by the stored pointer and then stores a copy of
|
|
<code>p</code>, which must have been allocated via a C++ <code>new</code> expression or be 0.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Since the previous object needs to be deleted, <code>T</code> must be a complete type.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_ptr_indirection">indirection</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>T & operator*() const noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Returns a reference to the object pointed to by the stored pointer. Behavior is undefined if the stored pointer is 0.</p>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>T * operator->() const noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_ptr_get">get</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>T * get() const noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Returns the stored pointer. <code>T</code> need not be a complete type.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_ptr_conversions">conversions</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>explicit operator bool () const noexcept; // never throws</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Returns <code>get() != 0</code>.</p>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
On C++03 compilers, the return value is of an unspecified type.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_ptr_swap">swap</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>void swap(scoped_ptr & b) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Exchanges the contents of the two smart pointers. <code>T</code> need not be a complete type.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="scoped_ptr_free_functions">Free Functions</h3>
|
|
<div class="sect3">
|
|
<h4 id="scoped_ptr_swap_2">swap</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Equivalent to <code>a.swap(b)</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_ptr_comparisons">comparisons</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>template<class T> bool operator==( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>template<class T> bool operator==( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Returns <code>p.get() == nullptr</code>.</p>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>template<class T> bool operator!=( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>template<class T> bool operator!=( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Returns <code>p.get() != nullptr</code>.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="scoped_ptr_example">Example</h3>
|
|
<div class="paragraph">
|
|
<p>Here’s an example that uses <code>scoped_ptr</code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>#include <boost/scoped_ptr.hpp>
|
|
#include <iostream>
|
|
|
|
struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } };
|
|
|
|
class MyClass {
|
|
boost::scoped_ptr<int> ptr;
|
|
public:
|
|
MyClass() : ptr(new int) { *ptr = 0; }
|
|
int add_one() { return ++*ptr; }
|
|
};
|
|
|
|
int main()
|
|
{
|
|
boost::scoped_ptr<Shoe> x(new Shoe);
|
|
MyClass my_instance;
|
|
std::cout << my_instance.add_one() << '\n';
|
|
std::cout << my_instance.add_one() << '\n';
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The example program produces the beginning of a child’s nursery rhyme:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>1
|
|
2
|
|
Buckle my shoe</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="scoped_ptr_rationale">Rationale</h3>
|
|
<div class="paragraph">
|
|
<p>The primary reason to use <code>scoped_ptr</code> rather than <code>std::auto_ptr</code> or <code>std::unique_ptr</code> is to let readers of your code
|
|
know that you intend "resource acquisition is initialization" to be applied only for the current scope, and have no intent to transfer ownership.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A secondary reason to use <code>scoped_ptr</code> is to prevent a later maintenance programmer from adding a function that transfers
|
|
ownership by returning the <code>auto_ptr</code>, because the maintenance programmer saw <code>auto_ptr</code>, and assumed ownership could safely be transferred.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Think of <code>bool</code> vs <code>int</code>. We all know that under the covers <code>bool</code> is usually just an <code>int</code>. Indeed, some argued against including bool in the C++
|
|
standard because of that. But by coding <code>bool</code> rather than <code>int</code>, you tell your readers what your intent is. Same with <code>scoped_ptr</code>; by using it you are signaling intent.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It has been suggested that <code>scoped_ptr<T></code> is equivalent to <code>std::auto_ptr<T> const</code>. Ed Brey pointed out, however, that <code>reset</code> will not work on a <code>std::auto_ptr<T> const</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="scoped_ptr_handlebody_idiom">Handle/Body Idiom</h3>
|
|
<div class="paragraph">
|
|
<p>One common usage of <code>scoped_ptr</code> is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation) in the header file.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The <code><a href="../../example/scoped_ptr_example_test.cpp">scoped_ptr_example_test.cpp</a></code> sample program includes a header file,
|
|
<code><a href="../../example/scoped_ptr_example.hpp">scoped_ptr_example.hpp</a></code>, which uses a <code>scoped_ptr<></code> to an incomplete type to hide the
|
|
implementation. The instantiation of member functions which require a complete type occurs in the <code><a href="../../example/scoped_ptr_example.cpp">scoped_ptr_example.cpp</a></code>
|
|
implementation file.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="scoped_ptr_frequently_asked_questions">Frequently Asked Questions</h3>
|
|
<div class="qlist qanda">
|
|
<ol>
|
|
<li>
|
|
<p><em>Why doesn’t <code>scoped_ptr</code> have a <code>release()</code> member?</em></p>
|
|
<p>When reading source code, it is valuable to be able to draw conclusions about program behavior based on the types being used. If <code>scoped_ptr</code> had a <code>release()</code> member,
|
|
it would become possible to transfer ownership of the held pointer, weakening its role as a way of limiting resource lifetime to a given context. Use <code>std::auto_ptr</code> where
|
|
transfer of ownership is required. (supplied by Dave Abrahams)</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="scoped_array">scoped_array: Scoped Array Ownership</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="scoped_array_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The <code>scoped_array</code> class template stores a pointer to a dynamically allocated array.
|
|
(Dynamically allocated arrays are allocated with the C++ <code>new[]</code> expression.) The array
|
|
pointed to is guaranteed to be deleted, either on destruction of the <code>scoped_array</code>,
|
|
or via an explicit <code>reset</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The <code>scoped_array</code> template is a simple solution for simple needs. It supplies a basic
|
|
"resource acquisition is initialization" facility, without shared-ownership or
|
|
transfer-of-ownership semantics. Both its name and enforcement of semantics
|
|
(by being noncopyable) signal its intent to retain ownership solely within the current scope.
|
|
Because it is noncopyable, it is safer than <code>shared_ptr<T[]></code> for pointers which should not be copied.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Because <code>scoped_array</code> is so simple, in its usual implementation every operation is as fast as a
|
|
built-in array pointer and it has no more space overhead that a built-in array pointer.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It cannot be used in C++ standard library containers. See <code>shared_ptr<T[]></code> if <code>scoped_array</code>
|
|
does not meet your needs.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It cannot correctly hold a pointer to a single object. See <code>scoped_ptr</code> for that usage.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>std::vector</code> is an alternative to <code>scoped_array</code> that is a bit heavier duty but far more flexible.
|
|
<code>boost::array</code> is an alternative that does not use dynamic allocation.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The class template is parameterized on <code>T</code>, the type of the object pointed to.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="scoped_array_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>scoped_array</code> is defined in <code><boost/smart_ptr/scoped_array.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
|
|
template<class T> class scoped_array {
|
|
private:
|
|
|
|
scoped_array(scoped_array const &);
|
|
scoped_array & operator=(scoped_array const &);
|
|
|
|
void operator==( scoped_array const& ) const;
|
|
void operator!=( scoped_array const& ) const;
|
|
|
|
public:
|
|
|
|
typedef T element_type;
|
|
|
|
explicit scoped_array(T * p = 0) noexcept;
|
|
~scoped_array() noexcept;
|
|
|
|
void reset(T * p = 0) noexcept;
|
|
|
|
T & operator[](std::ptrdiff_t i) const noexcept;
|
|
T * get() const noexcept;
|
|
|
|
explicit operator bool () const noexcept;
|
|
|
|
void swap(scoped_array & b) noexcept;
|
|
};
|
|
|
|
template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b) noexcept;
|
|
|
|
template<class T>
|
|
bool operator==( scoped_array<T> const & p, std::nullptr_t ) noexcept;
|
|
template<class T>
|
|
bool operator==( std::nullptr_t, scoped_array<T> const & p ) noexcept;
|
|
|
|
template<class T>
|
|
bool operator!=( scoped_array<T> const & p, std::nullptr_t ) noexcept;
|
|
template<class T>
|
|
bool operator!=( std::nullptr_t, scoped_array<T> const & p ) noexcept;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="scoped_array_members">Members</h3>
|
|
<div class="sect3">
|
|
<h4 id="scoped_array_element_type">element_type</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>typedef T element_type;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Provides the type of the stored pointer.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_array_constructors">constructors</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>explicit scoped_array(T * p = 0) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Constructs a <code>scoped_array</code>, storing a copy of <code>p</code>, which must have been
|
|
allocated via a C++ <code>new[]</code> expression or be 0. <code>T</code> is not required be a complete type.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_array_destructor">destructor</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>~scoped_array() noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Deletes the array pointed to by the stored pointer. Note that <code>delete[]</code> on a pointer with
|
|
a value of 0 is harmless. <code>T</code> must be complete, and <code>delete[]</code> on the stored pointer must
|
|
not throw exceptions.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_array_reset">reset</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>void reset(T * p = 0) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Deletes the array pointed to by the stored pointer and then stores a copy of <code>p</code>,
|
|
which must have been allocated via a C++ <code>new[]</code> expression or be 0. <code>T</code> must be complete,
|
|
and <code>delete[]</code> on the stored pointer must not throw exceptions.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_array_subscripting">subscripting</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>T & operator[](std::ptrdiff_t i) const noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Returns a reference to element <code>i</code> of the array pointed to by the stored pointer.
|
|
Behavior is undefined and almost certainly undesirable if the stored pointer is 0,
|
|
or if <code>i</code> is less than 0 or is greater than or equal to the number of elements in
|
|
the array.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_array_get">get</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>T * get() const noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Returns the stored pointer. <code>T</code> need not be a complete type.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_array_conversions">conversions</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>explicit operator bool () const noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Returns <code>get() != 0</code>.</p>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
On C++03 compilers, the return value is of an unspecified type.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_array_swap">swap</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>void swap(scoped_array & b) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Exchanges the contents of the two smart pointers. <code>T</code> need not be a complete type.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="scoped_array_free_functions">Free Functions</h3>
|
|
<div class="sect3">
|
|
<h4 id="scoped_array_swap_2">swap</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Equivalent to <code>a.swap(b)</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="scoped_array_comparisons">comparisons</h4>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>template<class T>
|
|
bool operator==( scoped_array<T> const & p, std::nullptr_t ) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>template<class T>
|
|
bool operator==( std::nullptr_t, scoped_array<T> const & p ) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Returns <code>p.get() == nullptr</code>.</p>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>template<class T>
|
|
bool operator!=( scoped_array<T> const & p, std::nullptr_t ) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>template<class T>
|
|
bool operator!=( std::nullptr_t, scoped_array<T> const & p ) noexcept;</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Returns <code>p.get() != nullptr</code>.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="shared_ptr">shared_ptr: Shared Ownership</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="shared_ptr_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The <code>shared_ptr</code> class template stores a pointer to a dynamically allocated object, typically with a C++ <code>new</code>-expression.
|
|
The object pointed to is guaranteed to be deleted when the last <code>shared_ptr</code> pointing to it is destroyed or reset.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="title">Code Example 1. Using shared_ptr</div>
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr<X> p1( new X );
|
|
shared_ptr<void> p2( new int(5) );</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>shared_ptr</code> deletes the exact pointer that has been passed at construction time, complete with its original type, regardless
|
|
of the template parameter. In the second example above, when <code>p2</code> is destroyed or reset, it will call <code>delete</code> on the original
|
|
<code>int*</code> that has been passed to the constructor, even though <code>p2</code> itself is of type <code>shared_ptr<void></code> and stores a pointer of
|
|
type <code>void*</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Every <code>shared_ptr</code> meets the <code>CopyConstructible</code>, <code>MoveConstructible</code>, <code>CopyAssignable</code> and <code>MoveAssignable</code> requirements of the
|
|
C++ Standard Library, and can be used in standard library containers. Comparison operators are supplied so that <code>shared_ptr</code>
|
|
works with the standard library’s associative containers.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Because the implementation uses reference counting, cycles of <code>shared_ptr</code> instances will not be reclaimed. For example, if <code>main()</code>
|
|
holds a <code>shared_ptr</code> to <code>A</code>, which directly or indirectly holds a <code>shared_ptr</code> back to <code>A</code>, <code>A’s use count will be 2. Destruction
|
|
of the original `shared_ptr</code> will leave <code>A</code> dangling with a use count of 1. Use <code><a href="#weak_ptr">weak_ptr</a></code> to "break cycles."</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The class template is parameterized on <code>T</code>, the type of the object pointed to. <code>shared_ptr</code> and most of its member functions place
|
|
no requirements on <code>T</code>; it is allowed to be an incomplete type, or <code>void</code>. Member functions that do place additional requirements
|
|
(constructors, <code>reset</code>) are explicitly documented below.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>shared_ptr<T></code> can be implicitly converted to <code>shared_ptr<U></code> whenever <code>T*</code> can be implicitly converted to <code>U*</code>. In particular,
|
|
<code>shared_ptr<T></code> is implicitly convertible to <code>shared_ptr<T const></code>, to <code>shared_ptr<U></code> where <code>U</code> is an accessible base of <code>T</code>,
|
|
and to <code>shared_ptr<void></code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>shared_ptr</code> is now part of the C++11 Standard, as <code>std::shared_ptr</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Starting with Boost release 1.53, <code>shared_ptr</code> can be used to hold a pointer to a dynamically allocated array. This is accomplished
|
|
by using an array type (<code>T[]</code> or <code>T[N]</code>) as the template parameter. There is almost no difference between using an unsized array,
|
|
<code>T[]</code>, and a sized array, <code>T[N]</code>; the latter just enables <code>operator[]</code> to perform a range check on the index.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="title">Code Example 2. Using shared_ptr with arrays</div>
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr<double[1024]> p1( new double[1024] );
|
|
shared_ptr<double[]> p2( new double[n] );</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="shared_ptr_best_practices">Best Practices</h3>
|
|
<div class="paragraph">
|
|
<p>A simple guideline that nearly eliminates the possibility of memory leaks is: always use a named smart pointer variable to hold the result
|
|
of <code>new</code>. Every occurence of the <code>new</code> keyword in the code should have the form:</p>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>shared_ptr<T> p(new Y);</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It is, of course, acceptable to use another smart pointer in place of <code>shared_ptr</code> above; having <code>T</code> and <code>Y</code> be the same type, or passing
|
|
arguments to the constructor of <code>Y</code> is also OK.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you observe this guideline, it naturally follows that you will have no explicit <code>delete</code> statements; <code>try</code>/<code>catch</code> constructs will be rare.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Avoid using unnamed <code>shared_ptr</code> temporaries to save typing; to see why this is dangerous, consider this example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="title">Code Example 3. Exception-safe and -unsafe use of shared_ptr</div>
|
|
<div class="content">
|
|
<pre class="highlight"><code>void f(shared_ptr<int>, int);
|
|
int g();
|
|
|
|
void ok()
|
|
{
|
|
shared_ptr<int> p( new int(2) );
|
|
f( p, g() );
|
|
}
|
|
|
|
void bad()
|
|
{
|
|
f( shared_ptr<int>( new int(2) ), g() );
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The function <code>ok</code> follows the guideline to the letter, whereas <code>bad</code> constructs the temporary <code>shared_ptr</code> in place, admitting the possibility of
|
|
a memory leak. Since function arguments are evaluated in unspecified order, it is possible for <code>new int(2)</code> to be evaluated first, <code>g()</code> second,
|
|
and we may never get to the <code>shared_ptr</code> constructor if <code>g</code> throws an exception. See <a href="http://www.gotw.ca/gotw/056.htm">Herb Sutter’s treatment</a> of
|
|
the issue for more information.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The exception safety problem described above may also be eliminated by using the <code><a href="#make_shared">make_shared</a></code> or <code>allocate_shared</code> factory
|
|
functions defined in <code><boost/smart_ptr/make_shared.hpp></code>. These factory functions also provide an efficiency benefit by consolidating allocations.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="shared_ptr_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>shared_ptr</code> is defined in <code><boost/smart_ptr/shared_ptr.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
|
|
class bad_weak_ptr: public std::exception;
|
|
|
|
template<class T> class weak_ptr;
|
|
|
|
template<class T> class shared_ptr {
|
|
public:
|
|
|
|
typedef /*see below*/ element_type;
|
|
|
|
constexpr shared_ptr() noexcept;
|
|
constexpr shared_ptr(std::nullptr_t) noexcept;
|
|
|
|
template<class Y> explicit shared_ptr(Y * p);
|
|
template<class Y, class D> shared_ptr(Y * p, D d);
|
|
template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
|
|
template<class D> shared_ptr(std::nullptr_t p, D d);
|
|
template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);
|
|
|
|
~shared_ptr() noexcept;
|
|
|
|
shared_ptr(shared_ptr const & r) noexcept;
|
|
template<class Y> shared_ptr(shared_ptr<Y> const & r) noexcept;
|
|
|
|
shared_ptr(shared_ptr && r) noexcept;
|
|
template<class Y> shared_ptr(shared_ptr<Y> && r) noexcept;
|
|
|
|
template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
|
|
template<class Y> shared_ptr(shared_ptr<Y> && r, element_type * p) noexcept;
|
|
|
|
template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
|
|
|
|
template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
|
|
template<class Y> shared_ptr(std::auto_ptr<Y> && r);
|
|
|
|
template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
|
|
|
|
shared_ptr & operator=(shared_ptr const & r) noexcept;
|
|
template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r) noexcept;
|
|
|
|
shared_ptr & operator=(shared_ptr const && r) noexcept;
|
|
template<class Y> shared_ptr & operator=(shared_ptr<Y> const && r) noexcept;
|
|
|
|
template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
|
|
template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r);
|
|
|
|
template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r);
|
|
|
|
shared_ptr & operator=(std::nullptr_t) noexcept;
|
|
|
|
void reset() noexcept;
|
|
|
|
template<class Y> void reset(Y * p);
|
|
template<class Y, class D> void reset(Y * p, D d);
|
|
template<class Y, class D, class A> void reset(Y * p, D d, A a);
|
|
|
|
template<class Y> void reset(shared_ptr<Y> const & r, element_type * p) noexcept;
|
|
template<class Y> void reset(shared_ptr<Y> && r, element_type * p) noexcept;
|
|
|
|
T & operator*() const noexcept; // only valid when T is not an array type
|
|
T * operator->() const noexcept; // only valid when T is not an array type
|
|
|
|
// only valid when T is an array type
|
|
element_type & operator[](std::ptrdiff_t i) const noexcept;
|
|
|
|
element_type * get() const noexcept;
|
|
|
|
bool unique() const noexcept;
|
|
long use_count() const noexcept;
|
|
|
|
explicit operator bool() const noexcept;
|
|
|
|
void swap(shared_ptr & b) noexcept;
|
|
|
|
template<class Y> bool owner_before(shared_ptr<Y> const & r) const noexcept;
|
|
template<class Y> bool owner_before(weak_ptr<Y> const & r) const noexcept;
|
|
|
|
template<class Y> bool owner_equals(shared_ptr<Y> const & r) const noexcept;
|
|
template<class Y> bool owner_equals(weak_ptr<Y> const & r) const noexcept;
|
|
|
|
std::size_t owner_hash_value() const noexcept;
|
|
};
|
|
|
|
template<class T, class U>
|
|
bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
|
|
|
|
template<class T, class U>
|
|
bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
|
|
|
|
template<class T, class U>
|
|
bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
|
|
|
|
template<class T> bool operator==(shared_ptr<T> const & p, std::nullptr_t) noexcept;
|
|
template<class T> bool operator==(std::nullptr_t, shared_ptr<T> const & p) noexcept;
|
|
|
|
template<class T> bool operator!=(shared_ptr<T> const & p, std::nullptr_t) noexcept;
|
|
template<class T> bool operator!=(std::nullptr_t, shared_ptr<T> const & p) noexcept;
|
|
|
|
template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b) noexcept;
|
|
|
|
template<class T>
|
|
typename shared_ptr<T>::element_type *
|
|
get_pointer(shared_ptr<T> const & p) noexcept;
|
|
|
|
template<class T, class U>
|
|
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) noexcept;
|
|
|
|
template<class T, class U>
|
|
shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) noexcept;
|
|
|
|
template<class T, class U>
|
|
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) noexcept;
|
|
|
|
template<class T, class U>
|
|
shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r) noexcept;
|
|
|
|
template<class E, class T, class Y>
|
|
std::basic_ostream<E, T> &
|
|
operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
|
|
|
|
template<class D, class T> D * get_deleter(shared_ptr<T> const & p) noexcept;
|
|
|
|
template<class T> bool atomic_is_lock_free( shared_ptr<T> const * p ) noexcept;
|
|
|
|
template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) noexcept;
|
|
template<class T>
|
|
shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, int ) noexcept;
|
|
|
|
template<class T>
|
|
void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) noexcept;
|
|
template<class T>
|
|
void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept;
|
|
|
|
template<class T>
|
|
shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) noexcept;
|
|
template<class T>
|
|
shared_ptr<T> atomic_exchange_explicit(
|
|
shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept;
|
|
|
|
template<class T>
|
|
bool atomic_compare_exchange(
|
|
shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) noexcept;
|
|
template<class T>
|
|
bool atomic_compare_exchange_explicit(
|
|
shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, int, int ) noexcept;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="shared_ptr_members">Members</h3>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_element_type">element_type</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>typedef ... element_type;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>element_type</code> is <code>T</code> when <code>T</code> is not an array type, and <code>U</code> when <code>T</code> is <code>U[]</code> or <code>U[N]</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_default_constructor">default constructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>constexpr shared_ptr() noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>constexpr shared_ptr(std::nullptr_t) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs an empty <code>shared_ptr</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>use_count() == 0 && get() == 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_pointer_constructor">pointer constructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> explicit shared_ptr(Y * p);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>Y</code> must be a complete type. The expression <code>delete[] p</code>, when <code>T</code> is an array type, or <code>delete p</code>, when <code>T</code> is not an array type,
|
|
must be well-formed, well-defined, and not throw exceptions. When <code>T</code> is <code>U[N]</code>, <code>Y(*)[N]</code> must be convertible to <code>T*</code>; when <code>T</code> is <code>U[]</code>, <code>Y(*)[]</code>
|
|
must be convertible to <code>T*</code>; otherwise, <code>Y*</code> must be convertible to <code>T*</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>When <code>T</code> is not an array type, constructs a <code>shared_ptr</code> that owns the pointer <code>p</code>. Otherwise, constructs a <code>shared_ptr</code> that owns <code>p</code> and
|
|
a deleter of an unspecified type that calls <code>delete[] p</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>use_count() == 1 && get() == p</code>. If <code>T</code> is not an array type and <code>p</code> is unambiguously convertible to <code>enable_shared_from_this<V>*</code>
|
|
for some <code>V</code>, <code>p->shared_from_this()</code> returns a copy of <code>*this</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p><code>std::bad_alloc</code>, or an implementation-defined exception when a resource other than memory could not be obtained.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Exception safety</dt>
|
|
<dd>
|
|
<p>If an exception is thrown, the constructor calls <code>delete[] p</code>, when <code>T</code> is an array type, or <code>delete p</code>, when <code>T</code> is not an array type.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
<code>p</code> must be a pointer to an object that was allocated via a C++ <code>new</code> expression or be 0. The postcondition that use count is 1 holds even if <code>p</code>
|
|
is 0; invoking <code>delete</code> on a pointer that has a value of 0 is harmless.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
This constructor is a template in order to remember the actual pointer type passed. The destructor will call delete with the same pointer, complete
|
|
with its original type, even when <code>T</code> does not have a virtual destructor, or is <code>void</code>.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_constructors_taking_a_deleter">constructors taking a deleter</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y, class D> shared_ptr(Y * p, D d);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class D> shared_ptr(std::nullptr_t p, D d);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>D</code> must be <code>CopyConstructible</code>. The copy constructor and destructor of <code>D</code> must not throw. The expression <code>d(p)</code> must be well-formed, well-defined,
|
|
and not throw exceptions. <code>A</code> must be an <code>Allocator</code>, as described in section Allocator Requirements [allocator.requirements] of the C++ Standard.
|
|
When <code>T</code> is <code>U[N]</code>, <code>Y(*)[N]</code> must be convertible to <code>T*</code>; when <code>T</code> is <code>U[]</code>, <code>Y(*)[]</code> must be convertible to <code>T*</code>; otherwise, <code>Y*</code> must be convertible to <code>T*</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs a <code>shared_ptr</code> that owns the pointer <code>p</code> and the deleter <code>d</code>. The constructors taking an allocator a allocate memory using a copy of <code>a</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>use_count() == 1 && get() == p</code>. If <code>T</code> is not an array type and <code>p</code> is unambiguously convertible to <code>enable_shared_from_this<V>*</code> for some <code>V</code>,
|
|
<code>p->shared_from_this()</code> returns a copy of <code>*this</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p><code>std::bad_alloc</code>, or an implementation-defined exception when a resource other than memory could not be obtained.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Exception safety</dt>
|
|
<dd>
|
|
<p>If an exception is thrown, <code>d(p)</code> is called.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
When the the time comes to delete the object pointed to by <code>p</code>, the stored copy of <code>d</code> is invoked with the stored copy of <code>p</code> as an argument.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
Custom deallocators allow a factory function returning a <code>shared_ptr</code> to insulate the user from its memory allocation strategy. Since the deallocator
|
|
is not part of the type, changing the allocation strategy does not break source or binary compatibility, and does not require a client recompilation. For example,
|
|
a "no-op" deallocator is useful when returning a <code>shared_ptr</code> to a statically allocated object, and other variations allow a <code>shared_ptr</code> to be used as a wrapper
|
|
for another smart pointer, easing interoperability.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
The requirement that the copy constructor of <code>D</code> does not throw comes from the pass by value. If the copy constructor throws, the pointer would leak.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_copy_and_converting_constructors">copy and converting constructors</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr(shared_ptr const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> shared_ptr(shared_ptr<Y> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>Y*</code> should be convertible to <code>T*</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>If <code>r</code> is empty, constructs an empty <code>shared_ptr</code>; otherwise, constructs a <code>shared_ptr</code> that shares ownership with <code>r</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>get() == r.get() && use_count() == r.use_count()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_move_constructors">move constructors</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr(shared_ptr && r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> shared_ptr(shared_ptr<Y> && r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>Y*</code> should be convertible to <code>T*</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Move-constructs a <code>shared_ptr</code> from <code>r</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>*this</code> contains the old value of <code>r</code>. <code>r</code> is empty and <code>r.get() == 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_aliasing_constructor">aliasing constructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Copy-constructs a <code>shared_ptr</code> from <code>r</code>, while storing <code>p</code> instead.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>get() == p && use_count() == r.use_count()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_aliasing_move_constructor">aliasing move constructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> shared_ptr(shared_ptr<Y> && r, element_type * p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Move-constructs a <code>shared_ptr</code> from <code>r</code>, while storing <code>p</code> instead.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>get() == p</code> and <code>use_count()</code> equals the old count of <code>r</code>. <code>r</code> is empty and <code>r.get() == 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_weak_ptr_constructor">weak_ptr constructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>Y*</code> should be convertible to <code>T*</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs a <code>shared_ptr</code> that shares ownership with <code>r</code> and stores a copy of the pointer stored in <code>r</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>use_count() == r.use_count()</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p><code>bad_weak_ptr</code> when <code>r.use_count() == 0</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Exception safety</dt>
|
|
<dd>
|
|
<p>If an exception is thrown, the constructor has no effect.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_auto_ptr_constructors">auto_ptr constructors</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> shared_ptr(std::auto_ptr<Y> & r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> shared_ptr(std::auto_ptr<Y> && r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>Y*</code> should be convertible to <code>T*</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs a <code>shared_ptr</code>, as if by storing a copy of <code>r.release()</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>use_count() == 1</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p><code>std::bad_alloc</code>, or an implementation-defined exception when a resource other than memory could not be obtained.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Exception safety</dt>
|
|
<dd>
|
|
<p>If an exception is thrown, the constructor has no effect.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_unique_ptr_constructor">unique_ptr constructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>Y*</code> should be convertible to <code>T*</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>When <code>r.get() == 0</code>, equivalent to <code>shared_ptr()</code>;</p>
|
|
</li>
|
|
<li>
|
|
<p>When <code>D</code> is not a reference type, equivalent to <code>shared_ptr(r.release(), r.get_deleter())</code>;</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise, equivalent to <code>shared_ptr(r.release(), del)</code>, where <code>del</code> is a deleter that stores the reference <code>rd</code> returned
|
|
from <code>r.get_deleter()</code> and <code>del(p)</code> calls <code>rd(p)</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</dd>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p><code>std::bad_alloc</code>, or an implementation-defined exception when a resource other than memory could not be obtained.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Exception safety</dt>
|
|
<dd>
|
|
<p>If an exception is thrown, the constructor has no effect.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_destructor">destructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>~shared_ptr() noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>If <code>*this</code> is empty, or shares ownership with another <code>shared_ptr</code> instance (<code>use_count() > 1</code>), there are no side effects.</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise, if <code>*this</code> owns a pointer <code>p</code> and a deleter <code>d</code>, <code>d(p)</code> is called.</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise, <code>*this</code> owns a pointer <code>p</code>, and <code>delete p</code> is called.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_assignment">assignment</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr & operator=(shared_ptr const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>shared_ptr(r).swap(*this)</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>*this</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
The use count updates caused by the temporary object construction and destruction are not considered observable side effects,
|
|
and the implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
<div class="paragraph">
|
|
<p>In particular, in the example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr<int> p(new int);
|
|
shared_ptr<void> q(p);
|
|
p = p;
|
|
q = p;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>both assignments may be no-ops.</p>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr & operator=(shared_ptr && r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> shared_ptr & operator=(shared_ptr<Y> && r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>shared_ptr(std::move(r)).swap(*this)</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>*this</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr & operator=(std::nullptr_t) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>shared_ptr().swap(*this)</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>*this</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_reset">reset</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>void reset() noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>shared_ptr().swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> void reset(Y * p);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>shared_ptr(p).swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y, class D> void reset(Y * p, D d);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>shared_ptr(p, d).swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y, class D, class A> void reset(Y * p, D d, A a);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>shared_ptr(p, d, a).swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> void reset(shared_ptr<Y> const & r, element_type * p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>shared_ptr(r, p).swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> void reset(shared_ptr<Y> && r, element_type * p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>shared_ptr(std::move(r), p).swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_indirection">indirection</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>T & operator*() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>T</code> should not be an array type. The stored pointer must not be 0.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>*get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>T * operator->() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>T</code> should not be an array type. The stored pointer must not be 0.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>element_type & operator[](std::ptrdiff_t i) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>T</code> should be an array type. The stored pointer must not be 0. <code>i >= 0</code>. If <code>T</code> is <code>U[N]</code>, <code>i < N</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>get()[i]</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_get">get</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>element_type * get() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>The stored pointer.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_unique">unique</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>bool unique() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>use_count() == 1</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_use_count">use_count</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>long use_count() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>The number of <code>shared_ptr</code> objects, <code>*this</code> included, that share ownership with <code>*this</code>, or 0 when <code>*this</code> is empty.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_conversions">conversions</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>explicit operator bool() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>get() != 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
This conversion operator allows <code>shared_ptr</code> objects to be used in boolean contexts, like <code>if(p && p->valid()) {}</code>.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
The conversion to <code>bool</code> is not merely syntactic sugar. It allows <code>shared_ptr</code> variables to be declared in conditions when using
|
|
<code>dynamic_pointer_cast</code> or <code>weak_ptr::lock</code>.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
On C++03 compilers, the return value is of an unspecified type.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_swap">swap</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>void swap(shared_ptr & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Exchanges the contents of the two smart pointers.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_owner_before">owner_before</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> bool owner_before(shared_ptr<Y> const & r) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> bool owner_before(weak_ptr<Y> const & r) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>See the description of <code>operator<</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_owner_equals">owner_equals</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> bool owner_equals(shared_ptr<Y> const & r) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> bool owner_equals(weak_ptr<Y> const & r) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>true</code> if and only if <code>*this</code> and <code>r</code> share ownership or are both empty.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_owner_hash_value">owner_hash_value</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>std::size_t owner_hash_value() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>An unspecified hash value such that two instances that share ownership
|
|
have the same hash value.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="shared_ptr_free_functions">Free Functions</h3>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_comparison">comparison</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>a.get() == b.get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>a.get() != b.get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> bool operator==(shared_ptr<T> const & p, std::nullptr_t) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> bool operator==(std::nullptr_t, shared_ptr<T> const & p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>p.get() == 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> bool operator!=(shared_ptr<T> const & p, std::nullptr_t) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> bool operator!=(std::nullptr_t, shared_ptr<T> const & p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>p.get() != 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>An unspecified value such that</p>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>operator<</code> is a strict weak ordering as described in section [lib.alg.sorting] of the C++ standard;</p>
|
|
</li>
|
|
<li>
|
|
<p>under the equivalence relation defined by <code>operator<</code>, <code>!(a < b) && !(b < a)</code>, two <code>shared_ptr</code> instances
|
|
are equivalent if and only if they share ownership or are both empty.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
Allows <code>shared_ptr</code> objects to be used as keys in associative containers.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
The rest of the comparison operators are omitted by design.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_swap_2">swap</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>a.swap(b)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_get_pointer">get_pointer</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
typename shared_ptr<T>::element_type *
|
|
get_pointer(shared_ptr<T> const & p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>p.get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
Provided as an aid to generic programming. Used by <code>mem_fn</code>.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_static_pointer_cast">static_pointer_cast</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p>The expression <code>static_cast<T*>( (U*)0 )</code> must be well-formed.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>shared_ptr<T>( r, static_cast<typename shared_ptr<T>::element_type*>(r.get()) )</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock caution">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Caution</div>
|
|
</td>
|
|
<td class="content">
|
|
The seemingly equivalent expression <code>shared_ptr<T>(static_cast<T*>(r.get()))</code> will eventually
|
|
result in undefined behavior, attempting to delete the same object twice.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_const_pointer_cast">const_pointer_cast</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p>The expression <code>const_cast<T*>( (U*)0 )</code> must be well-formed.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>shared_ptr<T>( r, const_cast<typename shared_ptr<T>::element_type*>(r.get()) )</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_dynamic_pointer_cast">dynamic_pointer_cast</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p>The expression <code>dynamic_cast<T*>( (U*)0 )</code> must be well-formed.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>When <code>dynamic_cast<typename shared_ptr<T>::element_type*>(r.get())</code> returns a nonzero value <code>p</code>, <code>shared_ptr<T>(r, p)</code>;</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise, <code>shared_ptr<T>()</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_reinterpret_pointer_cast">reinterpret_pointer_cast</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p>The expression <code>reinterpret_cast<T*>( (U*)0 )</code> must be well-formed.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>shared_ptr<T>( r, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get()) )</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_operator">operator<<</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class E, class T, class Y>
|
|
std::basic_ostream<E, T> &
|
|
operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p><code>os << p.get();</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>os</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_get_deleter">get_deleter</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class D, class T>
|
|
D * get_deleter(shared_ptr<T> const & p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>If <code>*this</code> owns a deleter <code>d</code> of type (cv-unqualified) <code>D</code>, returns <code>&d</code>; otherwise returns 0.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_ptr_atomic_access">Atomic Access</h4>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
The function in this section are atomic with respect to the first <code>shared_ptr</code> argument,
|
|
identified by <code>*p</code>. Concurrent access to the same <code>shared_ptr</code> instance is not a data race, if
|
|
done exclusively by the functions in this section.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> bool atomic_is_lock_free( shared_ptr<T> const * p ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>false</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
This implementation is not lock-free.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, int ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>*p</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
The <code>int</code> argument is the <code>memory_order</code>, but this implementation does not use it, as it’s lock-based
|
|
and therefore always sequentially consistent.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p><code>p->swap(r)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
shared_ptr<T> atomic_exchange_explicit(
|
|
shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p><code>p->swap(r)</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>The old value of <code>*p</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
bool atomic_compare_exchange(
|
|
shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
bool atomic_compare_exchange_explicit(
|
|
shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, int, int ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>If <code>*p</code> is equivalent to <code>*v</code>, assigns <code>w</code> to <code>*p</code>, otherwise assigns <code>*p</code> to <code>*v</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>true</code> if <code>*p</code> was equivalent to <code>*v</code>, <code>false</code> otherwise.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Remarks</dt>
|
|
<dd>
|
|
<p>Two <code>shared_ptr</code> instances are equivalent if they store the same pointer value and <em>share ownership</em>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="shared_ptr_example">Example</h3>
|
|
<div class="paragraph">
|
|
<p>See <a href="../../example/shared_ptr_example.cpp">shared_ptr_example.cpp</a> for a complete example program. The program builds a
|
|
<code>std::vector</code> and <code>std::set</code> of <code>shared_ptr</code> objects.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Note that after the containers have been populated, some of the <code>shared_ptr</code> objects will have a use count of 1 rather than
|
|
a use count of 2, since the set is a <code>std::set</code> rather than a <code>std::multiset</code>, and thus does not contain duplicate entries.
|
|
Furthermore, the use count may be even higher at various times while <code>push_back</code> and <code>insert</code> container operations are performed.
|
|
More complicated yet, the container operations may throw exceptions under a variety of circumstances. Getting the memory management
|
|
and exception handling in this example right without a smart pointer would be a nightmare.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="shared_ptr_handlebody_idiom">Handle/Body Idiom</h3>
|
|
<div class="paragraph">
|
|
<p>One common usage of <code>shared_ptr</code> is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation)
|
|
in the header file.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The <a href="../../example/shared_ptr_example2_test.cpp">shared_ptr_example2_test.cpp</a> sample program includes a header file,
|
|
<a href="../../example/shared_ptr_example2.hpp">shared_ptr_example2.hpp</a>, which uses a <code>shared_ptr</code> to an incomplete type to hide the implementation.
|
|
The instantiation of member functions which require a complete type occurs in the <a href="../../example/shared_ptr_example2.cpp">shared_ptr_example2.cpp</a>
|
|
implementation file. Note that there is no need for an explicit destructor. Unlike <code>~scoped_ptr</code>, <code>~shared_ptr</code> does not require that <code>T</code> be a complete type.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="shared_ptr_thread_safety">Thread Safety</h3>
|
|
<div class="paragraph">
|
|
<p><code>shared_ptr</code> objects offer the same level of thread safety as built-in types. A <code>shared_ptr</code> instance can be "read" (accessed using only const operations)
|
|
simultaneously by multiple threads. Different <code>shared_ptr</code> instances can be "written to" (accessed using mutable operations such as <code>operator=</code> or <code>reset</code>)
|
|
simultaneously by multiple threads (even when these instances are copies, and share the same reference count underneath.)</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Any other simultaneous accesses result in undefined behavior.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Examples:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr<int> p(new int(42));</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="title">Code Example 4. Reading a <code>shared_ptr</code> from two threads</div>
|
|
<div class="content">
|
|
<pre class="highlight"><code>// thread A
|
|
shared_ptr<int> p2(p); // reads p
|
|
|
|
// thread B
|
|
shared_ptr<int> p3(p); // OK, multiple reads are safe</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="title">Code Example 5. Writing different <code>shared_ptr</code> instances from two threads</div>
|
|
<div class="content">
|
|
<pre class="highlight"><code>// thread A
|
|
p.reset(new int(1912)); // writes p
|
|
|
|
// thread B
|
|
p2.reset(); // OK, writes p2</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="title">Code Example 6. Reading and writing a <code>shared_ptr</code> from two threads</div>
|
|
<div class="content">
|
|
<pre class="highlight"><code>// thread A
|
|
p = p3; // reads p3, writes p
|
|
|
|
// thread B
|
|
p3.reset(); // writes p3; undefined, simultaneous read/write</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="title">Code Example 7. Reading and destroying a <code>shared_ptr</code> from two threads</div>
|
|
<div class="content">
|
|
<pre class="highlight"><code>// thread A
|
|
p3 = p2; // reads p2, writes p3
|
|
|
|
// thread B
|
|
// p2 goes out of scope: undefined, the destructor is considered a "write access"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="title">Code Example 8. Writing a <code>shared_ptr</code> from two threads</div>
|
|
<div class="content">
|
|
<pre class="highlight"><code>// thread A
|
|
p3.reset(new int(1));
|
|
|
|
// thread B
|
|
p3.reset(new int(2)); // undefined, multiple writes</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Starting with Boost release 1.33.0, <code>shared_ptr</code> uses a lock-free implementation on most common platforms.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If your program is single-threaded and does not link to any libraries that might have used <code>shared_ptr</code> in its default configuration,
|
|
you can <code>#define</code> the macro <code>BOOST_SP_DISABLE_THREADS</code> on a project-wide basis to switch to ordinary non-atomic reference count updates.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>(Defining <code>BOOST_SP_DISABLE_THREADS</code> in some, but not all, translation units is technically a violation of the One Definition Rule and
|
|
undefined behavior. Nevertheless, the implementation attempts to do its best to accommodate the request to use non-atomic updates in those
|
|
translation units. No guarantees, though.)</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You can define the macro <code>BOOST_SP_USE_PTHREADS</code> to turn off the lock-free platform-specific implementation and fall back to the generic
|
|
<code>pthread_mutex_t</code>-based code.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="shared_ptr_frequently_asked_questions">Frequently Asked Questions</h3>
|
|
<div class="qlist qanda">
|
|
<ol>
|
|
<li>
|
|
<p><em>There are several variations of shared pointers, with different tradeoffs; why does the smart pointer library supply only a single implementation? It would be useful to be able to experiment with each type so as to find the most suitable for the job at hand?</em></p>
|
|
<p>An important goal of <code>shared_ptr</code> is to provide a standard shared-ownership pointer. Having a single pointer type is important for stable
|
|
library interfaces, since different shared pointers typically cannot interoperate, i.e. a reference counted pointer (used by library A)
|
|
cannot share ownership with a linked pointer (used by library B.)</p>
|
|
</li>
|
|
<li>
|
|
<p><em>Why doesn’t shared_ptr have template parameters supplying traits or policies to allow extensive user customization?</em></p>
|
|
<p>Parameterization discourages users. The <code>shared_ptr</code> template is carefully crafted to meet common needs without extensive parameterization.</p>
|
|
</li>
|
|
<li>
|
|
<p><em>I am not convinced. Default parameters can be used where appropriate to hide the complexity. Again, why not policies?</em></p>
|
|
<p>Template parameters affect the type. See the answer to the first question above.</p>
|
|
</li>
|
|
<li>
|
|
<p><em>Why doesn’t <code>shared_ptr</code> use a linked list implementation?</em></p>
|
|
<p>A linked list implementation does not offer enough advantages to offset the added cost of an extra pointer. In addition, it is expensive to
|
|
make a linked list implementation thread safe.</p>
|
|
</li>
|
|
<li>
|
|
<p><em>Why doesn’t <code>shared_ptr</code> (or any of the other Boost smart pointers) supply an automatic conversion to T*?</em></p>
|
|
<p>Automatic conversion is believed to be too error prone.</p>
|
|
</li>
|
|
<li>
|
|
<p><em>Why does <code>shared_ptr</code> supply <code>use_count()</code>?</em></p>
|
|
<p>As an aid to writing test cases and debugging displays. One of the progenitors had <code>use_count()</code>, and it was useful in tracking down bugs in
|
|
a complex project that turned out to have cyclic-dependencies.</p>
|
|
</li>
|
|
<li>
|
|
<p><em>Why doesn’t <code>shared_ptr</code> specify complexity requirements?</em></p>
|
|
<p>Because complexity requirements limit implementors and complicate the specification without apparent benefit to <code>shared_ptr</code> users. For example,
|
|
error-checking implementations might become non-conforming if they had to meet stringent complexity requirements.</p>
|
|
</li>
|
|
<li>
|
|
<p><em>Why doesn’t <code>shared_ptr</code> provide a <code>release()</code> function?</em></p>
|
|
<p><code>shared_ptr</code> cannot give away ownership unless it’s <code>unique()</code> because the other copy will still destroy the object.</p>
|
|
<div class="paragraph">
|
|
<p>Consider:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr<int> a(new int);
|
|
shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
|
|
|
|
int * p = a.release();
|
|
|
|
// Who owns p now? b will still call delete on it in its destructor.</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Furthermore, the pointer returned by <code>release()</code> would be difficult to deallocate reliably, as the source <code>shared_ptr</code> could have been created with a
|
|
custom deleter, or may have pointed to an object of a different type.</p>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p><em>Why is <code>operator->()</code> const, but its return value is a non-const pointer to the element type?</em></p>
|
|
<p>Shallow copy pointers, including raw pointers, typically don’t propagate constness. It makes little sense for them to do so, as you can always obtain a
|
|
non-const pointer from a const one and then proceed to modify the object through it. <code>shared_ptr</code> is "as close to raw pointers as possible but no closer".</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="weak_ptr">weak_ptr: Non-owning Observer</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="weak_ptr_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The <code>weak_ptr</code> class template stores a "weak reference" to an object that’s already managed by a <code>shared_ptr</code>.
|
|
To access the object, a <code>weak_ptr</code> can be converted to a <code>shared_ptr</code> using the <code>shared_ptr</code> constructor taking
|
|
<code>weak_ptr</code>, or the <code>weak_ptr</code> member function <code>lock</code>. When the last <code>shared_ptr</code> to the object goes away and the
|
|
object is deleted, the attempt to obtain a <code>shared_ptr</code> from the <code>weak_ptr</code> instances that refer to the deleted
|
|
object will fail: the constructor will throw an exception of type <code>boost::bad_weak_ptr</code>, and <code>weak_ptr::lock</code> will
|
|
return an empty <code>shared_ptr</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Every <code>weak_ptr</code> meets the <code>CopyConstructible</code> and <code>Assignable</code> requirements of the C++ Standard Library, and so
|
|
can be used in standard library containers. Comparison operators are supplied so that <code>weak_ptr</code> works with the standard
|
|
library’s associative containers.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>weak_ptr</code> operations never throw exceptions.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The class template is parameterized on <code>T</code>, the type of the object pointed to.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Compared to <code>shared_ptr</code>, <code>weak_ptr</code> provides a very limited subset of operations since accessing its stored pointer is
|
|
often dangerous in multithreaded programs, and sometimes unsafe even within a single thread (that is, it may invoke undefined
|
|
behavior.) Pretend for a moment that <code>weak_ptr</code> had a get member function that returned a raw pointer, and consider this innocent
|
|
piece of code:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr<int> p(new int(5));
|
|
weak_ptr<int> q(p);
|
|
|
|
// some time later
|
|
|
|
if(int * r = q.get())
|
|
{
|
|
// use *r
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Imagine that after the <code>if</code>, but immediately before <code>r</code> is used, another thread executes the statement <code>p.reset()</code>. Now <code>r</code> is a dangling pointer.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The solution to this problem is to create a temporary <code>shared_ptr</code> from <code>q</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr<int> p(new int(5));
|
|
weak_ptr<int> q(p);
|
|
|
|
// some time later
|
|
|
|
if(shared_ptr<int> r = q.lock())
|
|
{
|
|
// use *r
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Now <code>r</code> holds a reference to the object that was pointed by <code>q</code>. Even if <code>p.reset()</code> is executed in another thread, the object will stay alive until
|
|
<code>r</code> goes out of scope or is reset. By obtaining a <code>shared_ptr</code> to the object, we have effectively locked it against destruction.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="weak_ptr_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>weak_ptr</code> is defined in <code><boost/smart_ptr/weak_ptr.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
|
|
template<class T> class weak_ptr {
|
|
public:
|
|
|
|
typedef /*see below*/ element_type;
|
|
|
|
weak_ptr() noexcept;
|
|
|
|
template<class Y> weak_ptr(shared_ptr<Y> const & r) noexcept;
|
|
weak_ptr(weak_ptr const & r) noexcept;
|
|
template<class Y> weak_ptr(weak_ptr<Y> const & r) noexcept;
|
|
|
|
weak_ptr(weak_ptr && r) noexcept;
|
|
|
|
template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
|
|
template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept;
|
|
template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept;
|
|
|
|
~weak_ptr() noexcept;
|
|
|
|
weak_ptr & operator=(weak_ptr const & r) noexcept;
|
|
weak_ptr & operator=(weak_ptr && r) noexcept;
|
|
template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept;
|
|
template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r) noexcept;
|
|
|
|
long use_count() const noexcept;
|
|
bool expired() const noexcept;
|
|
|
|
bool empty() const noexcept;
|
|
|
|
shared_ptr<T> lock() const noexcept;
|
|
|
|
void reset() noexcept;
|
|
|
|
void swap(weak_ptr<T> & b) noexcept;
|
|
|
|
template<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept;
|
|
template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept;
|
|
|
|
template<class Y> bool owner_equals( weak_ptr<Y> const & r ) const noexcept;
|
|
template<class Y> bool owner_equals( shared_ptr<Y> const & r ) const noexcept;
|
|
|
|
std::size_t owner_hash_value() const noexcept;
|
|
};
|
|
|
|
template<class T, class U>
|
|
bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept;
|
|
|
|
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="weak_ptr_members">Members</h3>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_element_type">element_type</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>typedef ... element_type;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>element_type</code> is <code>T</code> when <code>T</code> is not an array type, and <code>U</code> when <code>T</code> is <code>U[]</code> or <code>U[N]</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_constructors">constructors</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>weak_ptr() noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs an empty <code>weak_ptr</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>use_count() == 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> weak_ptr(shared_ptr<Y> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>weak_ptr(weak_ptr const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> weak_ptr(weak_ptr<Y> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>If <code>r</code> is empty, constructs an empty <code>weak_ptr</code>; otherwise, constructs a <code>weak_ptr</code> that shares ownership with <code>r</code> as if by storing a copy of the pointer stored in <code>r</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>use_count() == r.use_count()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>weak_ptr(weak_ptr && r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs a <code>weak_ptr</code> that has the value <code>r</code> held.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>r</code> is empty.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_aliasing_constructors">aliasing constructors</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs a <code>weak_ptr</code> from <code>r</code> as if by using the corresponding converting/copy/move constructor, but stores <code>p</code> instead.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>use_count() == r.use_count()</code>. When <code>!expired()</code>, <code>shared_ptr<T>(*this).get() == p</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
These constructors are an extension, not present in <code>std::weak_ptr</code>.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_destructor">destructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>~weak_ptr() noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Destroys this <code>weak_ptr</code> but has no effect on the object its stored pointer points to.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_assignment">assignment</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>weak_ptr & operator=(weak_ptr const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>weak_ptr & operator=(weak_ptr && r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>weak_ptr(r).swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
The implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_use_count">use_count</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>long use_count() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>0 if <code>*this</code> is empty; otherwise, the number of <code>shared_ptr</code> objects that share ownership with <code>*this</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_expired">expired</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>bool expired() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>use_count() == 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_empty">empty</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>bool empty() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>true</code> when <code>*this</code> is empty, <code>false</code> otherwise.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
This function is an extension, not present in <code>std::weak_ptr</code>.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_lock">lock</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr<T> lock() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>expired()? shared_ptr<T>(): shared_ptr<T>(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_reset">reset</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>void reset() noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>weak_ptr().swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_swap">swap</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>void swap(weak_ptr & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Exchanges the contents of the two smart pointers.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_owner_before">owner_before</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>See the description of <code>operator<</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_owner_equals">owner_equals</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> bool owner_equals( weak_ptr<Y> const & r ) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> bool owner_equals( shared_ptr<Y> const & r ) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>true</code> if and only if <code>*this</code> and <code>r</code> share ownership or are both empty.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_owner_hash_value">owner_hash_value</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>std::size_t owner_hash_value() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>An unspecified hash value such that two instances that share ownership
|
|
have the same hash value.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="weak_ptr_free_functions">Free Functions</h3>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_comparison">comparison</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>An unspecified value such that</p>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>operator<</code> is a strict weak ordering as described in section [lib.alg.sorting] of the C++ standard;</p>
|
|
</li>
|
|
<li>
|
|
<p>under the equivalence relation defined by <code>operator<</code>, <code>!(a < b) && !(b < a)</code>, two <code>weak_ptr</code> instances
|
|
are equivalent if and only if they share ownership or are both empty.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
Allows <code>weak_ptr</code> objects to be used as keys in associative containers.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="weak_ptr_swap_2">swap</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>a.swap(b)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="weak_ptr_frequently_asked_questions">Frequently Asked Questions</h3>
|
|
<div class="qlist qanda">
|
|
<ol>
|
|
<li>
|
|
<p><em>Can an object create a weak_ptr to itself in its constructor?</em></p>
|
|
<p>No. A <code>weak_ptr</code> can only be created from a <code>shared_ptr</code>, and at object construction time no
|
|
<code>shared_ptr</code> to the object exists yet. Even if you could create a temporary <code>shared_ptr</code> to <code>this</code>,
|
|
it would go out of scope at the end of the constructor, and all <code>weak_ptr</code> instances would instantly expire.</p>
|
|
<div class="paragraph">
|
|
<p>The solution is to make the constructor private, and supply a factory function that returns a <code>shared_ptr</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>class X
|
|
{
|
|
private:
|
|
|
|
X();
|
|
|
|
public:
|
|
|
|
static shared_ptr<X> create()
|
|
{
|
|
shared_ptr<X> px(new X);
|
|
// create weak pointers from px here
|
|
return px;
|
|
}
|
|
};</code></pre>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="make_shared">make_shared: Creating shared_ptr</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="make_shared_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The function templates <code>make_shared</code> and <code>allocate_shared</code> provide convenient,
|
|
safe and efficient ways to create <code>shared_ptr</code> objects.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="make_shared_rationale">Rationale</h3>
|
|
<div class="paragraph">
|
|
<p>Consistent use of <code>shared_ptr</code> can eliminate the need to use an explicit
|
|
<code>delete</code>, but alone it provides no support in avoiding explicit <code>new</code>. There
|
|
were repeated requests from users for a factory function that creates an
|
|
object of a given type and returns a <code>shared_ptr</code> to it. Besides convenience
|
|
and style, such a function is also exception safe and considerably faster
|
|
because it can use a single allocation for both the object and its
|
|
corresponding control block, eliminating a significant portion of
|
|
<code>shared_ptr</code> construction overhead. This eliminates one of the major
|
|
efficiency complaints about <code>shared_ptr</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The family of overloaded function templates, <code>make_shared</code> and
|
|
<code>allocate_shared</code>, were provided to address this need. <code>make_shared</code> uses the
|
|
global <code>operator new</code> to allocate memory, whereas <code>allocate_shared</code> uses an
|
|
user-supplied allocator, allowing finer control.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The rationale for choosing the name <code>make_shared</code> is that the expression
|
|
<code>make_shared<Widget>()</code> can be read aloud and conveys the intended meaning.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Originally the Boost function templates <code>allocate_shared</code> and <code>make_shared</code>
|
|
were provided for scalar objects only. There was a need to have efficient
|
|
allocation of array objects. One criticism of class template <code>shared_array</code>
|
|
was always the lack of a utility like <code>make_shared</code> that uses only a single
|
|
allocation. When <code>shared_ptr</code> was enhanced to support array types, additional
|
|
overloads of <code>allocate_shared</code> and <code>make_shared</code> were provided for array
|
|
types.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="make_shared_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>make_shared</code> and <code>allocate_shared</code> are defined in
|
|
<code><boost/smart_ptr/make_shared.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
<code>// T is not an array</code>
|
|
template<class T, class... Args>
|
|
shared_ptr<T> make_shared(Args&&... args);
|
|
template<class T, class A, class... Args>
|
|
shared_ptr<T> allocate_shared(const A& a, Args&&... args);
|
|
|
|
<code>// T is an array of unknown bounds</code>
|
|
template<class T>
|
|
shared_ptr<T> make_shared(std::size_t n);
|
|
template<class T, class A>
|
|
shared_ptr<T> allocate_shared(const A& a, std::size_t n);
|
|
|
|
<code>// T is an array of known bounds</code>
|
|
template<class T>
|
|
shared_ptr<T> make_shared();
|
|
template<class T, class A>
|
|
shared_ptr<T> allocate_shared(const A& a);
|
|
|
|
<code>// T is an array of unknown bounds</code>
|
|
template<class T> shared_ptr<T>
|
|
make_shared(std::size_t n, const remove_extent_t<T>& v);
|
|
template<class T, class A> shared_ptr<T>
|
|
allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
|
|
|
|
<code>// T is an array of known bounds</code>
|
|
template<class T>
|
|
shared_ptr<T> make_shared(const remove_extent_t<T>& v);
|
|
template<class T, class A>
|
|
shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v);
|
|
|
|
<code>// T is not an array of unknown bounds</code>
|
|
template<class T>
|
|
shared_ptr<T> make_shared_noinit();
|
|
template<class T, class A>
|
|
shared_ptr<T> allocate_shared_noinit(const A& a);
|
|
|
|
<code>// T is an array of unknown bounds</code>
|
|
template<class T>
|
|
shared_ptr<T> make_shared_noinit(std::size_t n);
|
|
template<class T, class A>
|
|
shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n);
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="make_shared_common_requirements">Common Requirements</h3>
|
|
<div class="paragraph">
|
|
<p>The common requirements that apply to all <code>make_shared</code> and <code>allocate_shared</code>
|
|
overloads, unless specified otherwise, are described below.</p>
|
|
</div>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>A</code> shall be an <em>allocator</em>. The copy constructor and destructor
|
|
of <code>A</code> shall not throw exceptions.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Allocates memory for an object of type <code>T</code> or <code>n</code> objects of <code>U</code>
|
|
(if <code>T</code> is an array type of the form <code>U[]</code> and <code>n</code> is determined by
|
|
arguments, as specified by the concrete overload). The object is initialized
|
|
from arguments as specified by the concrete overload. Uses a rebound copy of
|
|
<code>a</code> (for an unspecified <code>value_type</code>) to allocate memory. If an exception is
|
|
thrown, the functions have no effect.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>shared_ptr</code> instance that stores and owns the address of the
|
|
newly constructed object.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>r.get() != 0</code> and <code>r.use_count() == 1</code>, where <code>r</code>
|
|
is the return value.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p><code>std::bad_alloc</code>, an exception thrown from <code>A::allocate</code>, or from the
|
|
initialization of the object.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Remarks</dt>
|
|
<dd>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Performs no more than one memory allocation. This provides efficiency
|
|
equivalent to an intrusive smart pointer.</p>
|
|
</li>
|
|
<li>
|
|
<p>When an object of an array type is specified to be initialized to a value of
|
|
the same type <code>v</code>, this shall be interpreted to mean that each array element
|
|
of the object is initialized to the corresponding element from <code>v</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>When an object of an array type is specified to be value-initialized, this
|
|
shall be interpreted to mean that each array element of the object is
|
|
value-initialized.</p>
|
|
</li>
|
|
<li>
|
|
<p>When a (sub)object of non-array type <code>U</code> is specified to be initialized to
|
|
a value <code>v</code>, or constructed from <code>args...</code>, <code>make_shared</code> shall perform
|
|
this initialization via the expression <code>::new(p) U(expr)</code> (where
|
|
<code><em>expr</em></code> is <code>v</code> or <code>std::forward<Args>(args)...)</code> respectively) and <code>p</code>
|
|
has type <code>void*</code> and points to storage suitable to hold an object of type
|
|
<code>U</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>When a (sub)object of non-array type <code>U</code> is specified to be initialized to
|
|
a value <code>v</code>, or constructed from <code>args...</code>, <code>allocate_shared</code> shall
|
|
perform this initialization via the expression
|
|
<code>std::allocator_traits<A2>::construct(a2, p, expr)</code> (where
|
|
<code><em>expr</em></code> is <code>v</code> or <code>std::forward<Args>(args)...)</code> respectively), <code>p</code>
|
|
points to storage suitable to hold an object of type <code>U</code>, and <code>a2</code> of
|
|
type <code>A2</code> is a potentially rebound copy of <code>a</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>When a (sub)object of non-array type <code>U</code> is specified to be
|
|
default-initialized, <code>make_shared_noinit</code> and <code>allocate_shared_noinit</code> shall
|
|
perform this initialization via the expression <code>::new(p) U</code>, where
|
|
<code>p</code> has type <code>void*</code> and points to storage suitable to hold an object of
|
|
type <code>U</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>When a (sub)object of non-array type <code>U</code> is specified to be
|
|
value-initialized, <code>make_shared</code> shall perform this initialization via the
|
|
expression <code>::new(p) U()</code>, where <code>p</code> has type <code>void*</code> and points to
|
|
storage suitable to hold an object of type <code>U</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>When a (sub)object of non-array type <code>U</code> is specified to be
|
|
value-initialized, <code>allocate_shared</code> shall perform this initialization via the
|
|
expression <code>std::allocator_traits<A2>::construct(a2, p)</code>, where
|
|
<code>p</code> points to storage suitable to hold an object of type <code>U</code> and <code>a2</code> of
|
|
type <code>A2</code> is a potentially rebound copy of <code>a</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Array elements are initialized in ascending order of their addresses.</p>
|
|
</li>
|
|
<li>
|
|
<p>When the lifetime of the object managed by the return value ends, or when
|
|
the initialization of an array element throws an exception, the initialized
|
|
elements should be destroyed in the reverse order of their construction.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
These functions will typically allocate more memory than the total size
|
|
of the element objects to allow for internal bookkeeping structures such as
|
|
the reference counts.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="make_shared_free_functions">Free Functions</h3>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class... Args>
|
|
shared_ptr<T> make_shared(Args&&... args);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A, class... Args>
|
|
shared_ptr<T> allocate_shared(const A& a, Args&&... args);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is not an array.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>shared_ptr</code> to an object of type <code>T</code>, constructed from
|
|
<code>args...</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Examples</dt>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = make_shared<int>();</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = make_shared<std::vector<int> >(16, 1);</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
shared_ptr<T> make_shared(std::size_t n);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A>
|
|
shared_ptr<T> allocate_shared(const A& a, std::size_t n);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is an array of unknown bounds.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>shared_ptr</code> to a sequence of <code>n</code> value-initialized objects of
|
|
type <code>remove_extent_t<T></code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Examples</dt>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = make_shared<double[]>(1024);</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = make_shared<double[][2][2]>(6);</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
shared_ptr<T> make_shared();</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A>
|
|
shared_ptr<T> allocate_shared(const A& a);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is an array of known bounds.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>shared_ptr</code> to a sequence of <code>extent_v<T></code> value-initialized
|
|
objects of type <code>remove_extent_t<T></code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Examples</dt>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = make_shared<double[1024]>();</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = make_shared<double[6][2][2]>();</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> shared_ptr<T>
|
|
make_shared(std::size_t n, const remove_extent_t<T>& v);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A> shared_ptr<T>
|
|
allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is an array of unknown bounds.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>shared_ptr</code> to a sequence of <code>n</code> objects of type
|
|
<code>remove_extent_t<T></code>, each initialized to <code>v</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Examples</dt>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = make_shared<double[]>(1024, 1.0);</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = make_shared<double[][2]>(6, {1.0, 0.0});</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = make_shared<std::vector<int>[]>(4, {1, 2});</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
shared_ptr<T> make_shared(const remove_extent_t<T>& v);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A>
|
|
shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is an array of known bounds.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>shared_ptr</code> to a sequence of <code>extent_v<T></code> objects of type
|
|
<code>remove_extent_t<T></code>, each initialized to <code>v</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Examples</dt>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = make_shared<double[1024]>(1.0);</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = make_shared<double[6][2]>({1.0, 0.0});</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = make_shared<std::vector<int>[4]>({1, 2});</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
shared_ptr<T> make_shared_noinit();</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A>
|
|
shared_ptr<T> allocate_shared_noinit(const A& a);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is not an array, or is an array of known bounds.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>shared_ptr</code> to a default-initialized object of type <code>T</code>, or a
|
|
sequence of <code>extent_v<T></code> default-initialized objects of type
|
|
<code>remove_extent_t<T></code>, respectively.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Example</dt>
|
|
<dd>
|
|
<p><code>auto p = make_shared_noinit<double[1024]>();</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
shared_ptr<T> make_shared_noinit(std::size_t n);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A>
|
|
shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is an array of unknown bounds.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>shared_ptr</code> to a sequence of <code><em>n</em></code> default-initialized objects
|
|
of type <code>remove_extent_t<T></code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Example</dt>
|
|
<dd>
|
|
<p><code>auto p = make_shared_noinit<double[]>(1024);</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="enable_shared_from_this">enable_shared_from_this</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="enable_shared_from_this_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The class template <code>enable_shared_from_this</code> is used as a base class that allows
|
|
a <code>shared_ptr</code> or a <code>weak_ptr</code> to the current object to be obtained from within a
|
|
member function.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>enable_shared_from_this<T></code> defines two member functions called <code>shared_from_this</code>
|
|
that return a <code>shared_ptr<T></code> and <code>shared_ptr<T const></code>, depending on constness, to
|
|
<code>this</code>. It also defines two member functions called <code>weak_from_this</code> that return a
|
|
corresponding <code>weak_ptr</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="enable_shared_from_this_example">Example</h3>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>#include <boost/enable_shared_from_this.hpp>
|
|
#include <boost/shared_ptr.hpp>
|
|
#include <cassert>
|
|
|
|
class Y: public boost::enable_shared_from_this<Y>
|
|
{
|
|
public:
|
|
|
|
boost::shared_ptr<Y> f()
|
|
{
|
|
return shared_from_this();
|
|
}
|
|
};
|
|
|
|
int main()
|
|
{
|
|
boost::shared_ptr<Y> p(new Y);
|
|
boost::shared_ptr<Y> q = p->f();
|
|
assert(p == q);
|
|
assert(!(p < q || q < p)); // p and q must share ownership
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="enable_shared_from_this_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>enable_shared_from_this</code> is defined in <code><boost/smart_ptr/enable_shared_from_this.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
|
|
template<class T> class enable_shared_from_this {
|
|
private:
|
|
|
|
// exposition only
|
|
weak_ptr<T> weak_this_;
|
|
|
|
protected:
|
|
|
|
enable_shared_from_this() = default;
|
|
~enable_shared_from_this() = default;
|
|
|
|
enable_shared_from_this(const enable_shared_from_this&) noexcept;
|
|
enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept;
|
|
|
|
public:
|
|
|
|
shared_ptr<T> shared_from_this();
|
|
shared_ptr<T const> shared_from_this() const;
|
|
|
|
weak_ptr<T> weak_from_this() noexcept;
|
|
weak_ptr<T const> weak_from_this() const noexcept;
|
|
}
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="enable_shared_from_this_members">Members</h3>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>enable_shared_from_this(enable_shared_from_this const &) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Default-constructs <code>weak_this_</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
<code>weak_this_</code> is <em>not</em> copied from the argument.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>enable_shared_from_this& operator=(enable_shared_from_this const &) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>*this</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
<code>weak_this_</code> is unchanged.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> shared_ptr<T> shared_from_this();</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> shared_ptr<T const> shared_from_this() const;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>shared_ptr<T>(weak_this_)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
These members throw <code>bad_weak_ptr</code> when <code>*this</code> is not owned by a <code>shared_ptr</code>.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
<div class="paragraph">
|
|
<p><code>weak_this_</code> is initialized by <code>shared_ptr</code> to a copy of itself when it’s constructed by a pointer to <code>*this</code>.
|
|
For example, in the following code:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>class Y: public boost::enable_shared_from_this<Y> {};
|
|
|
|
int main()
|
|
{
|
|
boost::shared_ptr<Y> p(new Y);
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>the construction of <code>p</code> will automatically initialize <code>p->weak_this_</code> to <code>p</code>.</p>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> weak_ptr<T> weak_from_this() noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> weak_ptr<T const> weak_from_this() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>weak_this_</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
Unlike <code>shared_from_this()</code>, <code>weak_from_this()</code> is valid in a destructor
|
|
and returns a <code>weak_ptr</code> that is <code>expired()</code> but still shares ownership
|
|
with other <code>weak_ptr</code> instances (if any) that refer to the object.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="enable_shared_from">enable_shared_from</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="enable_shared_from_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p><code>enable_shared_from</code> is used as a base class that allows a <code>shared_ptr</code> or a
|
|
<code>weak_ptr</code> to be obtained given a raw pointer to the object, by using the
|
|
functions <code>shared_from</code> and <code>weak_from</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>enable_shared_from</code> differs from <code>enable_shared_from_this<T></code> by the fact
|
|
that it’s not a template, and is its recommended replacement for new code.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="enable_shared_from_example">Example</h3>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>#include <boost/smart_ptr/enable_shared_from.hpp>
|
|
#include <boost/shared_ptr.hpp>
|
|
#include <cassert>
|
|
|
|
class Y: public boost::enable_shared_from
|
|
{
|
|
public:
|
|
|
|
boost::shared_ptr<Y> f()
|
|
{
|
|
return boost::shared_from( this );
|
|
}
|
|
};
|
|
|
|
int main()
|
|
{
|
|
boost::shared_ptr<Y> p(new Y);
|
|
boost::shared_ptr<Y> q = p->f();
|
|
assert(p == q);
|
|
assert(!(p < q || q < p)); // p and q must share ownership
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="enable_shared_from_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>enable_shared_from</code> is defined in <code><boost/smart_ptr/enable_shared_from.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
|
|
class enable_shared_from: public enable_shared_from_this<enable_shared_from>
|
|
{
|
|
};
|
|
|
|
template<class T> shared_ptr<T> shared_from( T * p );
|
|
template<class T> weak_ptr<T> weak_from( T * p ) noexcept;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="enable_shared_from_functions">Functions</h3>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> shared_ptr<T> shared_from( T * p );</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>shared_ptr<T>( p->enable_shared_from::shared_from_this(), p )</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
Throws <code>bad_weak_ptr</code> when <code>p</code> is not owned by a <code>shared_ptr</code>.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> weak_ptr<T> weak_from( T * p ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>weak_ptr<T>( p->enable_shared_from::weak_from_this(), p )</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
Unlike <code>shared_from(this)</code>, <code>weak_from(this)</code> is valid in a destructor
|
|
and returns a <code>weak_ptr</code> that is <code>expired()</code> but still shares ownership
|
|
with other <code>weak_ptr</code> instances (if any) that refer to the object.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="make_unique">make_unique: Creating unique_ptr</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="make_unique_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The <code>make_unique</code> function templates provide convenient and safe ways to
|
|
create <code>std::unique_ptr</code> objects.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="make_unique_rationale">Rationale</h3>
|
|
<div class="paragraph">
|
|
<p>The C++11 standard introduced <code>std::unique_ptr</code> but did not provide any
|
|
<code>make_unique</code> utility like <code>std::make_shared</code> that provided the same
|
|
exception safety and facility to avoid writing <code>new</code> expressions. Before it
|
|
was implemented by some standard library vendors (and prior to the C++14
|
|
standard introducing <code>std::make_unique</code>), this library provided it due to
|
|
requests from users.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This library also provides additional overloads of <code>make_unique</code> for
|
|
default-initialization, when users do not need or want to incur the expense
|
|
of value-initialization. The C++ standard does not yet provide this
|
|
feature with <code>std::make_unique</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="make_unique_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>make_unique</code> is defined in <code><boost/smart_ptr/make_unique.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
<code>// T is not an array</code>
|
|
template<class T, class... Args>
|
|
std::unique_ptr<T> make_unique(Args&&... args);
|
|
|
|
<code>// T is not an array</code>
|
|
template<class T>
|
|
std::unique_ptr<T> make_unique(type_identity_t<T>&& v);
|
|
|
|
<code>// T is an array of unknown bounds</code>
|
|
template<class T>
|
|
std::unique_ptr<T> make_unique(std::size_t n);
|
|
|
|
<code>// T is not an array</code>
|
|
template<class T>
|
|
std::unique_ptr<T> make_unique_noinit();
|
|
|
|
<code>// T is an array of unknown bounds</code>
|
|
template<class T>
|
|
std::unique_ptr<T> make_unique_noinit(std::size_t n);
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="make_unique_free_functions">Free Functions</h3>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class... Args>
|
|
std::unique_ptr<T> make_unique(Args&&... args);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is not an array.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>std::unique_ptr<T>(new T(std::forward<Args>(args)...)</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Example</dt>
|
|
<dd>
|
|
<p><code>auto p = make_unique<int>();</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
std::unique_ptr<T> make_unique(type_identity_t<T>&& v);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is not an array.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>std::unique_ptr<T>(new T(std::move(v))</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Example</dt>
|
|
<dd>
|
|
<p><code>auto p = make_unique<std::vector<int> >({1, 2});</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
std::unique_ptr<T> make_unique(std::size_t n);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is an array of unknown bounds.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>std::unique_ptr<T>(new remove_extent_t<T>[n]())</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Example</dt>
|
|
<dd>
|
|
<p><code>auto p = make_unique<double[]>(1024);</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
std::unique_ptr<T> make_unique_noinit();</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is not an array.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>std::unique_ptr<T>(new T)</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Example</dt>
|
|
<dd>
|
|
<p><code>auto p = make_unique_noinit<std::array<double, 1024> >();</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
std::unique_ptr<T> make_unique_noinit(std::size_t n);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is an array of unknown bounds.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>std::unique_ptr<T>(new remove_extent_t<T>[n])</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Example</dt>
|
|
<dd>
|
|
<p><code>auto p = make_unique_noinit<double[]>(1024);</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="allocate_unique">allocate_unique: Creating unique_ptr</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="allocate_unique_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The <code>allocate_unique</code> family of function templates provide convenient and safe
|
|
ways to obtain a <code>std::unique_ptr</code> that manages a new object created using an
|
|
allocator.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="allocate_unique_rationale">Rationale</h3>
|
|
<div class="paragraph">
|
|
<p>The C++14 standard introduced <code>std::make_unique</code> which used operator <code>new</code> to
|
|
create new objects. However, there is no convenient facility in the standard
|
|
library to use an allocator for the creation of the objects managed by
|
|
<code>std::unique_ptr</code>. Users writing allocator aware code have often requested an
|
|
<code>allocate_unique</code> factory function. This function is to <code>std::unique_ptr</code> what
|
|
<code>std::allocate_shared</code> is to <code>std::shared_ptr</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="allocate_unique_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>allocate_unique</code> is defined in <code><boost/smart_ptr/allocate_unique.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
template<class T, class A>
|
|
class alloc_deleter;
|
|
|
|
template<class T, class A>
|
|
using alloc_noinit_deleter = alloc_deleter<T, noinit_adaptor<A>>;
|
|
|
|
<code>// T is not an array</code>
|
|
template<class T, class A, class... Args>
|
|
std::unique_ptr<T, alloc_deleter<T, A>>
|
|
allocate_unique(const A& a, Args&&... args);
|
|
|
|
<code>// T is not an array</code>
|
|
template<class T, class A>
|
|
std::unique_ptr<T, alloc_deleter<T, A>>
|
|
allocate_unique(const A& a, type_identity_t<T>&& v);
|
|
|
|
<code>// T is an array of unknown bounds</code>
|
|
template<class T, class A>
|
|
std::unique_ptr<T, alloc_deleter<T, A>>
|
|
allocate_unique(const A& a, std::size_t n);
|
|
|
|
<code>// T is an array of known bounds</code>
|
|
template<class T, class A>
|
|
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
|
|
allocate_unique(const A& a);
|
|
|
|
<code>// T is an array of unknown bounds</code>
|
|
template<class T, class A>
|
|
std::unique_ptr<T, alloc_deleter<T, A>>
|
|
allocate_unique(const A& a, std::size_t n, const remove_extent_t<T>& v);
|
|
|
|
<code>// T is an array of known bounds</code>
|
|
template<class T, class A>
|
|
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
|
|
allocate_unique(const A& a, const remove_extent_t<T>& v);
|
|
|
|
<code>// T is not an array</code>
|
|
template<class T, class A>
|
|
std::unique_ptr<T, alloc_noinit_deleter<T, A>>
|
|
allocate_unique_noinit(const A& a);
|
|
|
|
<code>// T is an array of unknown bounds</code>
|
|
template<class T, class A>
|
|
std::unique_ptr<T, alloc_noinit_deleter<T, A>>
|
|
allocate_unique_noinit(const A& a, std::size_t n);
|
|
|
|
<code>// T is an array of known bounds</code>
|
|
template<class T, class A>
|
|
std::unique_ptr<remove_extent_t<T>[], alloc_noinit_deleter<T, A>>
|
|
allocate_unique_noinit(const A& a);
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="allocate_unique_common_requirements">Common Requirements</h3>
|
|
<div class="paragraph">
|
|
<p>The common requirements that apply to all <code>allocate_unique</code> and
|
|
<code>allocate_unique_noinit</code> overloads, unless specified otherwise, are described
|
|
below.</p>
|
|
</div>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>A</code> shall be an <em>allocator</em>. The copy constructor and destructor
|
|
of <code>A</code> shall not throw exceptions.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Allocates memory for an object of type <code>T</code> or <code>n</code> objects of <code>U</code>
|
|
(if <code>T</code> is an array type of the form <code>U[]</code> and <code>n</code> is determined by
|
|
arguments, as specified by the concrete overload). The object is initialized
|
|
from arguments as specified by the concrete overload. Uses a rebound copy of
|
|
<code>a</code> (for an unspecified <code>value_type</code>) to allocate memory. If an exception is
|
|
thrown, the functions have no effect.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>std::unique_ptr</code> instance that stores and owns the address of the
|
|
newly constructed object.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>r.get() != 0</code>, where <code>r</code> is the return value.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p>An exception thrown from <code>A::allocate</code>, or from the initialization of
|
|
the object.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Remarks</dt>
|
|
<dd>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>When an object of an array type is specified to be initialized to a value of
|
|
the same type <code>v</code>, this shall be interpreted to mean that each array element
|
|
of the object is initialized to the corresponding element from <code>v</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>When an object of an array type is specified to be value-initialized, this
|
|
shall be interpreted to mean that each array element of the object is
|
|
value-initialized.</p>
|
|
</li>
|
|
<li>
|
|
<p>When a (sub)object of non-array type <code>U</code> is specified to be initialized to a
|
|
value <code>v</code>, or constructed from <code>args...</code>, <code>allocate_unique</code> shall perform this
|
|
initialization via the expression
|
|
<code>std::allocator_traits<A2>::construct(a2, p, expr)</code> (where <code><em>expr</em></code> is <code>v</code> or
|
|
<code>std::forward<Args>(args)...)</code> respectively), <code>p</code> points to storage suitable
|
|
to hold an object of type <code>U</code>, and <code>a2</code> of type <code>A2</code> is a potentially rebound
|
|
copy of <code>a</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>When a (sub)object of non-array type <code>U</code> is specified to be
|
|
default-initialized, <code>allocate_unique_noinit</code> shall perform this initialization
|
|
via the expression <code>::new(p) U</code>, where <code>p</code> has type <code>void*</code> and points to
|
|
storage suitable to hold an object of type <code>U</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>When a (sub)object of non-array type <code>U</code> is specified to be
|
|
value-initialized, <code>allocate_unique</code> shall perform this initialization via the
|
|
expression <code>std::allocator_traits<A2>::construct(a2, p)</code>, where <code>p</code> points to
|
|
storage suitable to hold an object of type <code>U</code> and <code>a2</code> of type <code>A2</code> is a
|
|
potentially rebound copy of <code>a</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Array elements are initialized in ascending order of their addresses.</p>
|
|
</li>
|
|
<li>
|
|
<p>When the lifetime of the object managed by the return value ends, or when the
|
|
initialization of an array element throws an exception, the initialized
|
|
elements should be destroyed in the reverse order of their construction.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="allocate_unique_free_functions">Free Functions</h3>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A, class... Args>
|
|
std::unique_ptr<T, alloc_deleter<T, A>>
|
|
allocate_unique(const A& a, Args&&... args);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is not an array.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>std::unique_ptr</code> to an object of type <code>T</code>, constructed from
|
|
<code>args...</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Examples</dt>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = allocate_unique<int>(a);</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = allocate_unique<std::vector<int>>(a, 16, 1);</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A>
|
|
std::unique_ptr<T, alloc_deleter<T, A>>
|
|
allocate_unique(const A& a, type_identity_t<T>&& v);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is not an array.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>std::unique_ptr</code> to an object of type <code>T</code>, constructed from <code>v</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Example</dt>
|
|
<dd>
|
|
<p><code>auto p = allocate_unique<std::vector<int>>(a, {1, 2});</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A>
|
|
std::unique_ptr<T, alloc_deleter<T, A>>
|
|
allocate_unique(const A& a, std::size_t n);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is an array of unknown bounds.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>std::unique_ptr</code> to a sequence of <code>n</code> value-initialized objects of
|
|
type <code>remove_extent_t<T></code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Examples</dt>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = allocate_unique<double[]>(a, 1024);</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = allocate_unique<double[][2][2]>(a, 6);</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A>
|
|
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
|
|
allocate_unique(const A& a);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is an array of known bounds.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>std::unique_ptr</code> to a sequence of <code>extent_v<T></code> value-initialized
|
|
objects of type <code>remove_extent_t<T></code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Examples</dt>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = allocate_unique<double[1024]>(a);</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = allocate_unique<double[6][2][2]>(a);</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A>
|
|
std::unique_ptr<T, alloc_deleter<T, A>>
|
|
allocate_unique(const A& a, std::size_t n, const remove_extent_t<T>& v);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is an array of unknown bounds.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>std::unique_ptr</code> to a sequence of <code>n</code> objects of type
|
|
<code>remove_extent_t<T></code>, each initialized to <code>v</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Examples</dt>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = allocate_unique<double[]>(a, 1024, 1.0);</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = allocate_unique<double[][2]>(a, 6, {1.0, 0.0});</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = allocate_unique<std::vector<int>[]>(a, 4, {1, 2});</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A>
|
|
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
|
|
allocate_unique(const A& a, const remove_extent_t<T>& v);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is an array of known bounds.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>std::unique_ptr</code> to a sequence of <code>extent_v<T></code> objects of type
|
|
<code>remove_extent_t<T></code>, each initialized to <code>v</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Examples</dt>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = allocate_unique<double[1024]>(a, 1.0);</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = allocate_unique<double[6][2]>(a, {1.0, 0.0});</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>auto p = allocate_unique<std::vector<int>[4]>(a, {1, 2});</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A>
|
|
std::unique_ptr<T, alloc_noinit_deleter<T, A>>
|
|
allocate_unique_noinit(const A& a);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is not an array.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>std::unique_ptr</code> to a default-initialized object of type <code>T</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Example</dt>
|
|
<dd>
|
|
<p><code>auto p = allocate_unique_noinit<double>(a);</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A>
|
|
std::unique_ptr<T, alloc_noinit_deleter<T, A>>
|
|
allocate_unique_noinit(const A& a, std::size_t n);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is an array of unknown bounds.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>std::unique_ptr</code> to a sequence of <code>n</code> default-initialized objects
|
|
of type <code>remove_extent_t<T></code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Example</dt>
|
|
<dd>
|
|
<p><code>auto p = allocate_unique_noinit<double[]>(a, 1024);</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A>
|
|
std::unique_ptr<remove_extent_t<T>, alloc_noinit_deleter<T, A>>
|
|
allocate_unique_noinit(const A& a);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Constraints</dt>
|
|
<dd>
|
|
<p><code>T</code> is an array of known bounds.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A <code>std::unique_ptr</code> to a sequence of <code>extent_v<T></code>
|
|
default-initialized objects of type <code>remove_extent_t<T></code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Example</dt>
|
|
<dd>
|
|
<p><code>auto p = allocate_unique_noinit<double[1024]>(a);</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="allocate_unique_deleter">Deleter</h3>
|
|
<div class="paragraph">
|
|
<p>Class template <code>alloc_deleter</code> is the deleter used by the <code>allocate_unique</code>
|
|
functions.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="allocate_unique_synopsis_2">Synopsis</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class A>
|
|
class alloc_deleter {
|
|
public:
|
|
using pointer = <code>unspecified</code>;
|
|
|
|
explicit alloc_deleter(const A& a) noexcept;
|
|
|
|
void operator()(pointer p);
|
|
};</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="allocate_unique_members">Members</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>using pointer = <code>unspecified</code>;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="paragraph">
|
|
<p>A type that satisfies <em>NullablePointer</em>.</p>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>explicit alloc_deleter(const A& a) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Initializes the stored allocator from <code>a</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>void operator()(pointer p);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Destroys the objects and deallocates the storage referenced by <code>p</code>,
|
|
using the stored allocator.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="intrusive_ptr">intrusive_ptr: Managing Objects with Embedded Counts</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="intrusive_ptr_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The <code>intrusive_ptr</code> class template stores a pointer to an object with an embedded reference count.
|
|
Every new <code>intrusive_ptr</code> instance increments the reference count by using an unqualified call to the
|
|
function <code>intrusive_ptr_add_ref</code>, passing it the pointer as an argument. Similarly, when an <code>intrusive_ptr</code>
|
|
is destroyed, it calls <code>intrusive_ptr_release</code>; this function is responsible for destroying the object when
|
|
its reference count drops to zero. The user is expected to provide suitable definitions of these two functions.
|
|
On compilers that support argument-dependent lookup, <code>intrusive_ptr_add_ref</code> and <code>intrusive_ptr_release</code> should
|
|
be defined in the namespace that corresponds to their parameter; otherwise, the definitions need to go in namespace
|
|
<code>boost</code>. The library provides a helper base class template <code><a href="#intrusive_ref_counter">intrusive_ref_counter</a></code> which
|
|
may help adding support for <code>intrusive_ptr</code> to user types.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The class template is parameterized on <code>T</code>, the type of the object pointed to. <code>intrusive_ptr<T></code> can be implicitly
|
|
converted to <code>intrusive_ptr<U></code> whenever <code>T*</code> can be implicitly converted to <code>U*</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The main reasons to use <code>intrusive_ptr</code> are:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Some existing frameworks or OSes provide objects with embedded reference counts;</p>
|
|
</li>
|
|
<li>
|
|
<p>The memory footprint of <code>intrusive_ptr</code> is the same as the corresponding raw pointer;</p>
|
|
</li>
|
|
<li>
|
|
<p><code>intrusive_ptr<T></code> can be constructed from an arbitrary raw pointer of type <code>T*</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As a general rule, if it isn’t obvious whether <code>intrusive_ptr</code> better fits your needs than <code>shared_ptr</code>, try a <code>shared_ptr</code>-based design first.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="intrusive_ptr_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>intrusive_ptr</code> is defined in <code><boost/smart_ptr/intrusive_ptr.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
|
|
template<class T> class intrusive_ptr {
|
|
public:
|
|
|
|
typedef T element_type;
|
|
|
|
intrusive_ptr() noexcept;
|
|
intrusive_ptr(T * p, bool add_ref = true);
|
|
|
|
intrusive_ptr(intrusive_ptr const & r);
|
|
template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
|
|
|
|
intrusive_ptr(intrusive_ptr && r);
|
|
template<class Y> intrusive_ptr(intrusive_ptr<Y> && r);
|
|
|
|
~intrusive_ptr();
|
|
|
|
intrusive_ptr & operator=(intrusive_ptr const & r);
|
|
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
|
|
intrusive_ptr & operator=(T * r);
|
|
|
|
intrusive_ptr & operator=(intrusive_ptr && r);
|
|
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> && r);
|
|
|
|
void reset();
|
|
void reset(T * r);
|
|
void reset(T * r, bool add_ref);
|
|
|
|
T & operator*() const noexcept;
|
|
T * operator->() const noexcept;
|
|
T * get() const noexcept;
|
|
T * detach() noexcept;
|
|
|
|
explicit operator bool () const noexcept;
|
|
|
|
void swap(intrusive_ptr & b) noexcept;
|
|
};
|
|
|
|
template<class T, class U>
|
|
bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
|
|
|
|
template<class T, class U>
|
|
bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
|
|
|
|
template<class T, class U>
|
|
bool operator==(intrusive_ptr<T> const & a, U * b) noexcept;
|
|
|
|
template<class T, class U>
|
|
bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept;
|
|
|
|
template<class T, class U>
|
|
bool operator==(T * a, intrusive_ptr<U> const & b) noexcept;
|
|
|
|
template<class T, class U>
|
|
bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept;
|
|
|
|
template<class T>
|
|
bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept;
|
|
|
|
template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept;
|
|
|
|
template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept;
|
|
|
|
template<class T, class U>
|
|
intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r) noexcept;
|
|
|
|
template<class T, class U>
|
|
intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r) noexcept;
|
|
|
|
template<class T, class U>
|
|
intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r) noexcept;
|
|
|
|
template<class E, class T, class Y>
|
|
std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os,
|
|
intrusive_ptr<Y> const & p);
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="intrusive_ptr_members">Members</h3>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_element_type">element_type</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>typedef T element_type;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Provides the type of the template parameter T.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_constructors">constructors</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>intrusive_ptr() noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>get() == 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>intrusive_ptr(T * p, bool add_ref = true);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p><code>if(p != 0 && add_ref) intrusive_ptr_add_ref(p);</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>get() == p</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>intrusive_ptr(intrusive_ptr const & r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p><code>T * p = r.get(); if(p != 0) intrusive_ptr_add_ref(p);</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>get() == r.get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>intrusive_ptr(intrusive_ptr && r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> intrusive_ptr(intrusive_ptr<Y> && r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>get()</code> equals the old value of <code>r.get()</code>. <code>r.get() == 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_destructor">destructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>~intrusive_ptr();</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p><code>if(get() != 0) intrusive_ptr_release(get());</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_assignment">assignment</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>intrusive_ptr & operator=(intrusive_ptr const & r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>intrusive_ptr & operator=(T * r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>intrusive_ptr(r).swap(*this)</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>*this</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>intrusive_ptr & operator=(intrusive_ptr && r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> && r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>intrusive_ptr(std::move(r)).swap(*this)</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>*this</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_reset">reset</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>void reset();</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>intrusive_ptr().swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>void reset(T * r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>intrusive_ptr(r).swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>void reset(T * r, bool add_ref);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>intrusive_ptr(r, add_ref).swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_indirection">indirection</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>T & operator*() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requirements</dt>
|
|
<dd>
|
|
<p><code>get() != 0</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>*get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>T * operator->() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requirements</dt>
|
|
<dd>
|
|
<p><code>get() != 0</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_get">get</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>T * get() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>the stored pointer.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_detach">detach</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>T * detach() noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>the stored pointer.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>get() == 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
The returned pointer has an elevated reference count. This allows conversion of an <code>intrusive_ptr</code>
|
|
back to a raw pointer, without the performance overhead of acquiring and dropping an extra reference.
|
|
It can be viewed as the complement of the non-reference-incrementing constructor.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="admonitionblock caution">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Caution</div>
|
|
</td>
|
|
<td class="content">
|
|
Using <code>detach</code> escapes the safety of automatic reference counting provided by <code>intrusive_ptr</code>.
|
|
It should by used only where strictly necessary (such as when interfacing to an existing API), and when
|
|
the implications are thoroughly understood.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_conversions">conversions</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>explicit operator bool () const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>get() != 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
This conversion operator allows <code>intrusive_ptr</code> objects to be used in boolean contexts,
|
|
like <code>if (p && p->valid()) {}</code>.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
On C++03 compilers, the return value is of an unspecified type.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_swap">swap</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>void swap(intrusive_ptr & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Exchanges the contents of the two smart pointers.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="intrusive_ptr_free_functions">Free Functions</h3>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_comparison">comparison</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>a.get() == b.get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>a.get() != b.get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator==(intrusive_ptr<T> const & a, U * b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>a.get() == b</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>a.get() != b</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator==(T * a, intrusive_ptr<U> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>a == b.get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>a != b.get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>std::less<T *>()(a.get(), b.get())</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
Allows <code>intrusive_ptr</code> objects to be used as keys in associative containers.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_swap_2">swap</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>a.swap(b)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_get_pointer">get_pointer</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>p.get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
Provided as an aid to generic programming. Used by <code>mem_fn</code>.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_static_pointer_cast">static_pointer_cast</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>intrusive_ptr<T>(static_cast<T*>(r.get()))</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_const_pointer_cast">const_pointer_cast</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>intrusive_ptr<T>(const_cast<T*>(r.get()))</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_dynamic_pointer_cast">dynamic_pointer_cast</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>intrusive_ptr<T>(dynamic_cast<T*>(r.get()))</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ptr_operator">operator<<</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class E, class T, class Y>
|
|
std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os,
|
|
intrusive_ptr<Y> const & p);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p><code>os << p.get();</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>os</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="intrusive_ref_counter">intrusive_ref_counter</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="intrusive_ref_counter_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The <code>intrusive_ref_counter</code> class template implements a reference counter for
|
|
a derived user’s class that is intended to be used with <code>intrusive_ptr</code>. The
|
|
base class has associated <code>intrusive_ptr_add_ref</code> and <code>intrusive_ptr_release</code>
|
|
functions which modify the reference counter as needed and destroy the user’s
|
|
object when the counter drops to zero.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The class template is parameterized on <code>Derived</code> and <code>CounterPolicy</code>
|
|
parameters. The first parameter is the user’s class that derives from
|
|
<code>intrusive_ref_counter</code>. This type is needed in order to destroy the object
|
|
correctly when there are no references to it left.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The second parameter is a policy that defines the nature of the reference
|
|
counter. The library provides two such policies: <code>thread_unsafe_counter</code> and
|
|
<code>thread_safe_counter</code>. The former instructs the <code>intrusive_ref_counter</code> base
|
|
class to use a counter only suitable for a single-threaded use. Pointers to a
|
|
single object that uses this kind of reference counter must not be used in
|
|
different threads. The latter policy makes the reference counter thread-safe,
|
|
unless the target platform doesn’t support threading. Since in modern systems
|
|
support for threading is common, the default counter policy is
|
|
<code>thread_safe_counter</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="intrusive_ref_counter_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>intrusive_ref_counter</code> is defined in
|
|
<code><boost/smart_ptr/intrusive_ref_counter.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
struct thread_unsafe_counter;
|
|
struct thread_safe_counter;
|
|
|
|
template<class Derived, class CounterPolicy = thread_safe_counter>
|
|
class intrusive_ref_counter {
|
|
public:
|
|
intrusive_ref_counter() noexcept;
|
|
intrusive_ref_counter(const intrusive_ref_counter& v) noexcept;
|
|
|
|
intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept;
|
|
|
|
unsigned int use_count() const noexcept;
|
|
|
|
protected:
|
|
~intrusive_ref_counter() = default;
|
|
};
|
|
|
|
template<class Derived, class CounterPolicy>
|
|
void intrusive_ptr_add_ref(
|
|
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
|
|
|
|
template<class Derived, class CounterPolicy>
|
|
void intrusive_ptr_release(
|
|
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="intrusive_ref_counter_members">Members</h3>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ref_counter_constructors">Constructors</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>intrusive_ref_counter() noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>intrusive_ref_counter(const intrusive_ref_counter&) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>use_count() == 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
The pointer to the constructed object is expected to be passed to
|
|
<code>intrusive_ptr</code> constructor, assignment operator or <code>reset</code> method, which
|
|
would increment the reference counter.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ref_counter_destructor">Destructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>~intrusive_ref_counter();</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Destroys the counter object.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
The destructor is protected so that the object can only be destroyed
|
|
through the <code>Derived</code> class.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ref_counter_assignment">Assignment</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Does nothing, reference counter is not modified.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ref_counter_use_count">use_count</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>unsigned int use_count() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>The current value of the reference counter.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
The returned value may not be actual in multi-threaded applications.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="intrusive_ref_counter_free_functions">Free Functions</h3>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ref_counter_intrusive_ptr_add_ref">intrusive_ptr_add_ref</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Derived, class CounterPolicy>
|
|
void intrusive_ptr_add_ref(
|
|
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Increments the reference counter.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="intrusive_ref_counter_intrusive_ptr_release">intrusive_ptr_release</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Derived, class CounterPolicy>
|
|
void intrusive_ptr_release(
|
|
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Decrements the reference counter. If the reference counter reaches
|
|
0, calls <code>delete static_cast<const Derived*>(p)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="local_shared_ptr">local_shared_ptr: Shared Ownership within a Single Thread</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="local_shared_ptr_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p><code>local_shared_ptr</code> is nearly identical to <code>shared_ptr</code>, with the only difference of note being that its reference count is
|
|
updated with non-atomic operations. As such, a <code>local_shared_ptr</code> and all its copies must reside in (be local to) a single
|
|
thread (hence the name.)</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>local_shared_ptr</code> can be converted to <code>shared_ptr</code> and vice versa. Creating a <code>local_shared_ptr</code> from a <code>shared_ptr</code> creates
|
|
a new local reference count; this means that two <code>local_shared_ptr</code> instances, both created from the same <code>shared_ptr</code>, refer
|
|
to the same object but don’t share the same count, and as such, can safely be used by two different threads.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="title">Code Example 9. Two local_shared_ptr instances created from a shared_ptr</div>
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr<X> p1( new X );
|
|
|
|
local_shared_ptr<X> p2( p1 ); // p2.local_use_count() == 1
|
|
local_shared_ptr<X> p3( p1 ); // p3.local_use_count() also 1</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Creating the second <code>local_shared_ptr</code> from the first one, however, does lead to the two sharing the same count:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="title">Code Example 10. A local_shared_ptr created from another local_shared_ptr</div>
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr<X> p1( new X );
|
|
|
|
local_shared_ptr<X> p2( p1 ); // p2.local_use_count() == 1
|
|
local_shared_ptr<X> p3( p2 ); // p3.local_use_count() == 2</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Two <code>shared_ptr</code> instances created from the same <code>local_shared_ptr</code> do share ownership:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="title">Code Example 11. Two shared_ptr instances created from a local_shared_ptr</div>
|
|
<div class="content">
|
|
<pre class="highlight"><code>local_shared_ptr<X> p1( new X );
|
|
|
|
shared_ptr<X> p2( p1 ); // p2.use_count() == 2
|
|
shared_ptr<X> p3( p1 ); // p3.use_count() == 3</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here <code>p2.use_count()</code> is 2, because <code>p1</code> holds a reference, too.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>One can think of <code>local_shared_ptr<T></code> as <code>shared_ptr<shared_ptr<T>></code>, with the outer <code>shared_ptr</code> using non-atomic operations for
|
|
its count. Converting from <code>local_shared_ptr</code> to <code>shared_ptr</code> gives you a copy of the inner <code>shared_ptr</code>; converting from <code>shared_ptr</code>
|
|
wraps it into an outer <code>shared_ptr</code> with a non-atomic use count (conceptually speaking) and returns the result.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="local_shared_ptr_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>local_shared_ptr</code> is defined in <code><boost/smart_ptr/local_shared_ptr.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
|
|
template<class T> class local_shared_ptr {
|
|
public:
|
|
|
|
typedef /*see below*/ element_type;
|
|
|
|
// constructors
|
|
|
|
constexpr local_shared_ptr() noexcept;
|
|
constexpr local_shared_ptr(std::nullptr_t) noexcept;
|
|
|
|
template<class Y> explicit local_shared_ptr(Y * p);
|
|
|
|
template<class Y, class D> local_shared_ptr(Y * p, D d);
|
|
template<class D> local_shared_ptr(std::nullptr_t p, D d);
|
|
|
|
template<class Y, class D, class A> local_shared_ptr(Y * p, D d, A a);
|
|
template<class D, class A> local_shared_ptr(std::nullptr_t p, D d, A a);
|
|
|
|
local_shared_ptr(local_shared_ptr const & r) noexcept;
|
|
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r) noexcept;
|
|
|
|
local_shared_ptr(local_shared_ptr && r) noexcept;
|
|
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r) noexcept;
|
|
|
|
template<class Y> local_shared_ptr( shared_ptr<Y> const & r );
|
|
template<class Y> local_shared_ptr( shared_ptr<Y> && r );
|
|
|
|
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r, element_type * p) noexcept;
|
|
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r, element_type * p) noexcept;
|
|
|
|
template<class Y, class D> local_shared_ptr(std::unique_ptr<Y, D> && r);
|
|
|
|
// destructor
|
|
|
|
~local_shared_ptr() noexcept;
|
|
|
|
// assignment
|
|
|
|
local_shared_ptr & operator=(local_shared_ptr const & r) noexcept;
|
|
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const & r) noexcept;
|
|
|
|
local_shared_ptr & operator=(local_shared_ptr const && r) noexcept;
|
|
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const && r) noexcept;
|
|
|
|
template<class Y, class D> local_shared_ptr & operator=(std::unique_ptr<Y, D> && r);
|
|
|
|
local_shared_ptr & operator=(std::nullptr_t) noexcept;
|
|
|
|
// reset
|
|
|
|
void reset() noexcept;
|
|
|
|
template<class Y> void reset(Y * p);
|
|
template<class Y, class D> void reset(Y * p, D d);
|
|
template<class Y, class D, class A> void reset(Y * p, D d, A a);
|
|
|
|
template<class Y> void reset(local_shared_ptr<Y> const & r, element_type * p) noexcept;
|
|
template<class Y> void reset(local_shared_ptr<Y> && r, element_type * p) noexcept;
|
|
|
|
// accessors
|
|
|
|
T & operator*() const noexcept; // only valid when T is not an array type
|
|
T * operator->() const noexcept; // only valid when T is not an array type
|
|
|
|
// only valid when T is an array type
|
|
element_type & operator[](std::ptrdiff_t i) const noexcept;
|
|
|
|
element_type * get() const noexcept;
|
|
|
|
long local_use_count() const noexcept;
|
|
|
|
// conversions
|
|
|
|
explicit operator bool() const noexcept;
|
|
|
|
template<class Y> operator shared_ptr<Y>() const noexcept;
|
|
template<class Y> operator weak_ptr<Y>() const noexcept;
|
|
|
|
// swap
|
|
|
|
void swap(local_shared_ptr & b) noexcept;
|
|
|
|
// owner_before
|
|
|
|
template<class Y> bool owner_before(local_shared_ptr<Y> const & r) const noexcept;
|
|
|
|
// owner_equals
|
|
|
|
template<class Y> bool owner_equals(local_shared_ptr<Y> const & r) const noexcept;
|
|
};
|
|
|
|
// comparisons
|
|
|
|
template<class T, class U>
|
|
bool operator==(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
|
|
template<class T, class U>
|
|
bool operator==(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
|
|
template<class T, class U>
|
|
bool operator==(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
|
|
|
|
template<class T, class U>
|
|
bool operator!=(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
|
|
template<class T, class U>
|
|
bool operator!=(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
|
|
template<class T, class U>
|
|
bool operator!=(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
|
|
|
|
template<class T> bool operator==(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
|
|
template<class T> bool operator==(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
|
|
|
|
template<class T> bool operator!=(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
|
|
template<class T> bool operator!=(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
|
|
|
|
template<class T, class U>
|
|
bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
|
|
|
|
// swap
|
|
|
|
template<class T> void swap(local_shared_ptr<T> & a, local_shared_ptr<T> & b) noexcept;
|
|
|
|
// get_pointer
|
|
|
|
template<class T>
|
|
typename local_shared_ptr<T>::element_type *
|
|
get_pointer(local_shared_ptr<T> const & p) noexcept;
|
|
|
|
// casts
|
|
|
|
template<class T, class U>
|
|
local_shared_ptr<T> static_pointer_cast(local_shared_ptr<U> const & r) noexcept;
|
|
|
|
template<class T, class U>
|
|
local_shared_ptr<T> const_pointer_cast(local_shared_ptr<U> const & r) noexcept;
|
|
|
|
template<class T, class U>
|
|
local_shared_ptr<T> dynamic_pointer_cast(local_shared_ptr<U> const & r) noexcept;
|
|
|
|
template<class T, class U>
|
|
local_shared_ptr<T> reinterpret_pointer_cast(local_shared_ptr<U> const & r) noexcept;
|
|
|
|
// stream I/O
|
|
|
|
template<class E, class T, class Y>
|
|
std::basic_ostream<E, T> &
|
|
operator<< (std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p);
|
|
|
|
// get_deleter
|
|
|
|
template<class D, class T> D * get_deleter(local_shared_ptr<T> const & p) noexcept;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="local_shared_ptr_members">Members</h3>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_element_type">element_type</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>typedef ... element_type;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>element_type</code> is <code>T</code> when <code>T</code> is not an array type, and <code>U</code> when <code>T</code> is <code>U[]</code> or <code>U[N]</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_default_constructor">default constructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>constexpr local_shared_ptr() noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>constexpr local_shared_ptr(std::nullptr_t) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs an empty <code>local_shared_ptr</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>local_use_count() == 0 && get() == 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_pointer_constructor">pointer constructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> explicit local_shared_ptr(Y * p);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs a <code>local_shared_ptr</code> that owns <code>shared_ptr<T>( p )</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>local_use_count() == 1 && get() == p</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p><code>std::bad_alloc</code>, or an implementation-defined exception when a resource other than memory could not be obtained.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_constructors_taking_a_deleter">constructors taking a deleter</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y, class D> local_shared_ptr(Y * p, D d);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class D> local_shared_ptr(std::nullptr_t p, D d);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs a <code>local_shared_ptr</code> that owns <code>shared_ptr<T>( p, d )</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>local_use_count() == 1 && get() == p</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p><code>std::bad_alloc</code>, or an implementation-defined exception when a resource other than memory could not be obtained.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y, class D, class A> local_shared_ptr(Y * p, D d, A a);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class D, class A> local_shared_ptr(std::nullptr_t p, D d, A a);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs a <code>local_shared_ptr</code> that owns <code>shared_ptr<T>( p, d, a )</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>local_use_count() == 1 && get() == p</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p><code>std::bad_alloc</code>, or an implementation-defined exception when a resource other than memory could not be obtained.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_copy_and_converting_constructors">copy and converting constructors</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>local_shared_ptr(local_shared_ptr const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>Y*</code> should be convertible to <code>T*</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>If <code>r</code> is empty, constructs an empty <code>local_shared_ptr</code>; otherwise, constructs a <code>local_shared_ptr</code> that shares ownership with <code>r</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>get() == r.get() && local_use_count() == r.local_use_count()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_move_constructors">move constructors</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>local_shared_ptr(local_shared_ptr && r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> local_shared_ptr(local_shared_ptr<Y> && r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>Y*</code> should be convertible to <code>T*</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Move-constructs a <code>local_shared_ptr</code> from <code>r</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>*this</code> contains the old value of <code>r</code>. <code>r</code> is empty and <code>r.get() == 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_shared_ptr_constructor">shared_ptr constructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> local_shared_ptr( shared_ptr<Y> const & r );</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> local_shared_ptr( shared_ptr<Y> && r );</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs a <code>local_shared_ptr</code> that owns <code>r</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>local_use_count() == 1</code>. <code>get()</code> returns the old value of <code>r.get()</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p><code>std::bad_alloc</code>, or an implementation-defined exception when a resource other than memory could not be obtained.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_aliasing_constructor">aliasing constructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r, element_type * p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>constructs a <code>local_shared_ptr</code> that shares ownership with <code>r</code> and stores <code>p</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>get() == p && local_use_count() == r.local_use_count()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_aliasing_move_constructor">aliasing move constructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> local_shared_ptr(local_shared_ptr<Y> && r, element_type * p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Move-constructs a <code>local_shared_ptr</code> from <code>r</code>, while storing <code>p</code> instead.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Postconditions</dt>
|
|
<dd>
|
|
<p><code>get() == p</code> and <code>local_use_count()</code> equals the old count of <code>r</code>. <code>r</code> is empty and <code>r.get() == 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_unique_ptr_constructor">unique_ptr constructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y, class D> local_shared_ptr(std::unique_ptr<Y, D> && r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>Y*</code> should be convertible to <code>T*</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>When <code>r.get() == 0</code>, equivalent to <code>local_shared_ptr()</code>;</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise, constructs a <code>local_shared_ptr</code> that owns <code>shared_ptr<T>( std::move(r) )</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</dd>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p><code>std::bad_alloc</code>, or an implementation-defined exception when a resource other than memory could not be obtained.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Exception safety</dt>
|
|
<dd>
|
|
<p>If an exception is thrown, the constructor has no effect.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_destructor">destructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>~local_shared_ptr() noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>If <code>*this</code> is empty, or shares ownership with another <code>local_shared_ptr</code> instance (<code>local_use_count() > 1</code>), there are no side effects.</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise, destroys the owned <code>shared_ptr</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_assignment">assignment</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>local_shared_ptr & operator=(local_shared_ptr const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>local_shared_ptr(r).swap(*this)</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>*this</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>local_shared_ptr & operator=(local_shared_ptr && r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> && r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y, class D> local_shared_ptr & operator=(std::unique_ptr<Y, D> && r);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>local_shared_ptr(std::move(r)).swap(*this)</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>*this</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>local_shared_ptr & operator=(std::nullptr_t) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>local_shared_ptr().swap(*this)</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>*this</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_reset">reset</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>void reset() noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>local_shared_ptr().swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> void reset(Y * p);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>local_shared_ptr(p).swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y, class D> void reset(Y * p, D d);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>local_shared_ptr(p, d).swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y, class D, class A> void reset(Y * p, D d, A a);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>local_shared_ptr(p, d, a).swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> void reset(local_shared_ptr<Y> const & r, element_type * p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>local_shared_ptr(r, p).swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> void reset(local_shared_ptr<Y> && r, element_type * p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>local_shared_ptr(std::move(r), p).swap(*this)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_indirection">indirection</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>T & operator*() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>T</code> should not be an array type.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>*get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>T * operator->() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>T</code> should not be an array type.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>element_type & operator[](std::ptrdiff_t i) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>T</code> should be an array type. The stored pointer must not be 0. <code>i >= 0</code>. If <code>T</code> is <code>U[N]</code>, <code>i < N</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>get()[i]</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_get">get</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>element_type * get() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>The stored pointer.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_local_use_count">local_use_count</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>long local_use_count() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>The number of <code>local_shared_ptr</code> objects, <code>*this</code> included, that share ownership with <code>*this</code>, or 0 when <code>*this</code> is empty.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_conversions">conversions</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>explicit operator bool() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>get() != 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
On C++03 compilers, the return value is of an unspecified type.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> operator shared_ptr<Y>() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> operator weak_ptr<Y>() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>T*</code> should be convertible to <code>Y*</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>a copy of the owned <code>shared_ptr</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_swap">swap</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>void swap(local_shared_ptr & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Exchanges the contents of the two smart pointers.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_owner_before">owner_before</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> bool owner_before(local_shared_ptr<Y> const & r) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>See the description of <code>operator<</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_owner_equals">owner_equals</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class Y> bool owner_equals(local_shared_ptr<Y> const & r) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>true</code> if and only if <code>*this</code> and <code>r</code> share ownership or are both empty.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="local_shared_ptr_free_functions">Free Functions</h3>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_comparison">comparison</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator==(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator==(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator==(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>a.get() == b.get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator!=(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator!=(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator!=(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>a.get() != b.get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> bool operator==(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> bool operator==(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>p.get() == 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> bool operator!=(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> bool operator!=(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>p.get() != 0</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>An unspecified value such that</p>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>operator<</code> is a strict weak ordering as described in section [lib.alg.sorting] of the C++ standard;</p>
|
|
</li>
|
|
<li>
|
|
<p>under the equivalence relation defined by <code>operator<</code>, <code>!(a < b) && !(b < a)</code>, two <code>local_shared_ptr</code> instances
|
|
are equivalent if and only if they share ownership or are both empty.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
Allows <code>local_shared_ptr</code> objects to be used as keys in associative containers.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
The rest of the comparison operators are omitted by design.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_swap_2">swap</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> void swap(local_shared_ptr<T> & a, local_shared_ptr<T> & b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Equivalent to <code>a.swap(b)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_get_pointer">get_pointer</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
typename local_shared_ptr<T>::element_type *
|
|
get_pointer(local_shared_ptr<T> const & p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>p.get()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
Provided as an aid to generic programming. Used by <code>mem_fn</code>.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_static_pointer_cast">static_pointer_cast</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
local_shared_ptr<T> static_pointer_cast(local_shared_ptr<U> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p>The expression <code>static_cast<T*>( (U*)0 )</code> must be well-formed.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>local_shared_ptr<T>( r, static_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock caution">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Caution</div>
|
|
</td>
|
|
<td class="content">
|
|
The seemingly equivalent expression <code>local_shared_ptr<T>(static_cast<T*>(r.get()))</code> will eventually
|
|
result in undefined behavior, attempting to delete the same object twice.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_const_pointer_cast">const_pointer_cast</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
local_shared_ptr<T> const_pointer_cast(local_shared_ptr<U> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p>The expression <code>const_cast<T*>( (U*)0 )</code> must be well-formed.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>local_shared_ptr<T>( r, const_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_dynamic_pointer_cast">dynamic_pointer_cast</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
local_shared_ptr<T> dynamic_pointer_cast(local_shared_ptr<U> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p>The expression <code>dynamic_cast<T*>( (U*)0 )</code> must be well-formed.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>When <code>dynamic_cast<typename local_shared_ptr<T>::element_type*>(r.get())</code> returns a nonzero value <code>p</code>, <code>local_shared_ptr<T>(r, p)</code>;</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise, <code>local_shared_ptr<T>()</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_reinterpret_pointer_cast">reinterpret_pointer_cast</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
local_shared_ptr<T> reinterpret_pointer_cast(local_shared_ptr<U> const & r) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p>The expression <code>reinterpret_cast<T*>( (U*)0 )</code> must be well-formed.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>local_shared_ptr<T>( r, reinterpret_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_operator">operator<<</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class E, class T, class Y>
|
|
std::basic_ostream<E, T> &
|
|
operator<< (std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p><code>os << p.get();</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>os</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="local_shared_ptr_get_deleter">get_deleter</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class D, class T>
|
|
D * get_deleter(local_shared_ptr<T> const & p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>If <code>*this</code> owns a <code>shared_ptr</code> instance <code>p</code>, <code>get_deleter<D>( p )</code>, otherwise 0.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="make_local_shared">make_local_shared: Creating local_shared_ptr</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="make_local_shared_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The function templates <code>make_local_shared</code> and <code>allocate_local_shared</code> provide
|
|
convenient, safe and efficient ways to create <code>local_shared_ptr</code> objects. They
|
|
are analogous to <code>make_shared</code> and <code>allocate_shared</code> for <code>shared_ptr</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="make_local_shared_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>make_local_shared</code> and <code>allocate_local_shared</code> are defined in
|
|
<code><boost/smart_ptr/make_local_shared.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
<code>// T is not an array</code>
|
|
template<class T, class... Args>
|
|
local_shared_ptr<T> make_local_shared(Args&&... args);
|
|
template<class T, class A, class... Args>
|
|
local_shared_ptr<T> allocate_local_shared(const A& a, Args&&... args);
|
|
|
|
<code>// T is an array of unknown bounds</code>
|
|
template<class T>
|
|
local_shared_ptr<T> make_local_shared(std::size_t n);
|
|
template<class T, class A>
|
|
local_shared_ptr<T> allocate_local_shared(const A& a, std::size_t n);
|
|
|
|
<code>// T is an array of known bounds</code>
|
|
template<class T>
|
|
local_shared_ptr<T> make_local_shared();
|
|
template<class T, class A>
|
|
local_shared_ptr<T> allocate_local_shared(const A& a);
|
|
|
|
<code>// T is an array of unknown bounds</code>
|
|
template<class T>
|
|
local_shared_ptr<T> make_local_shared(std::size_t n,
|
|
const remove_extent_t<T>& v);
|
|
template<class T, class A>
|
|
local_shared_ptr<T> allocate_local_shared(const A& a, std::size_t n,
|
|
const remove_extent_t<T>& v);
|
|
|
|
<code>// T is an array of known bounds</code>
|
|
template<class T>
|
|
local_shared_ptr<T> make_local_shared(const remove_extent_t<T>& v);
|
|
template<class T, class A>
|
|
local_shared_ptr<T> allocate_local_shared(const A& a,
|
|
const remove_extent_t<T>& v);
|
|
|
|
<code>// T is not an array of known bounds</code>
|
|
template<class T>
|
|
local_shared_ptr<T> make_local_shared_noinit();
|
|
template<class T, class A>
|
|
local_shared_ptr<T> allocate_local_shared_noinit(const A& a);
|
|
|
|
<code>// T is an array of unknown bounds</code>
|
|
template<class T>
|
|
local_shared_ptr<T> make_local_shared_noinit(std::size_t n);
|
|
template<class T, class A>
|
|
local_shared_ptr<T> allocate_local_shared_noinit(const A& a,
|
|
std::size_t n);
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="make_local_shared_description_2">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The requirements and effects of these functions are the same as <code>make_shared</code>
|
|
and <code>allocate_shared</code>, except that a <code>local_shared_ptr</code> is returned.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="pointer_cast">Generic Pointer Casts</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="pointer_cast_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The pointer cast function templates (<code>static_pointer_cast</code>,
|
|
<code>dynamic_pointer_cast</code>, <code>const_pointer_cast</code>, and <code>reinterpret_pointer_cast</code>)
|
|
provide a way to write generic pointer castings for raw pointers,
|
|
<code>std::shared_ptr</code> and <code>std::unique_ptr</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>There is test and example code in
|
|
<a href="../../test/pointer_cast_test.cpp">pointer_cast_test.cpp</a></p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="pointer_cast_rationale">Rationale</h3>
|
|
<div class="paragraph">
|
|
<p>Boost smart pointers usually overload those functions to provide a mechanism
|
|
to emulate pointers casts. For example, <code>shared_ptr<T></code> implements a static
|
|
pointer cast this way:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U>
|
|
shared_ptr<T> static_pointer_cast(const shared_ptr<U>& p);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Pointer cast functions templates are overloads of <code>static_pointer_cast</code>,
|
|
<code>dynamic_pointer_cast</code>, <code>const_pointer_cast</code>, and <code>reinterpret_pointer_cast</code>
|
|
for raw pointers, <code>std::shared_ptr</code> and <code>std::unique_ptr</code>. This way when
|
|
developing pointer type independent classes, for example, memory managers or
|
|
shared memory compatible classes, the same code can be used for raw and smart
|
|
pointers.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="pointer_cast_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p>The generic pointer casts are defined in <code><boost/pointer_cast.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
template<class T, class U> T* static_pointer_cast(U* p) noexcept;
|
|
template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
|
|
template<class T, class U> T* const_pointer_cast(U* p) noexcept;
|
|
template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
|
|
|
|
template<class T, class U> std::shared_ptr<T>
|
|
static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
|
template<class T, class U> std::shared_ptr<T>
|
|
dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
|
template<class T, class U> std::shared_ptr<T>
|
|
const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
|
template<class T, class U> std::shared_ptr<T>
|
|
reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
|
|
|
template<class T, class U> std::unique_ptr<T>
|
|
static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
|
template<class T, class U> std::unique_ptr<T>
|
|
dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
|
template<class T, class U> std::unique_ptr<T>
|
|
const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
|
template<class T, class U> std::unique_ptr<T>
|
|
reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="pointer_cast_free_functions">Free Functions</h3>
|
|
<div class="sect3">
|
|
<h4 id="pointer_cast_static_pointer_cast">static_pointer_cast</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U> T* static_pointer_cast(U* p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>static_cast<T*>(p)</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U> std::shared_ptr<T>
|
|
static_pointer_cast(const std::shared_ptr<U>& p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>std::static_pointer_cast<T>(p)</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U> std::unique_ptr<T>
|
|
static_pointer_cast(std::unique_ptr<U>&& p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p>The expression <code>static_cast<T*>((U*)0)</code> must be well-formed.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>std::unique_ptr<T>(static_cast<typename
|
|
std::unique_ptr<T>::element_type*>(p.release()))</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock caution">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Caution</div>
|
|
</td>
|
|
<td class="content">
|
|
The seemingly equivalent expression
|
|
<code>std::unique_ptr<T>(static_cast<T*>(p.get()))</code> will eventually result in
|
|
undefined behavior, attempting to delete the same object twice.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="pointer_cast_dynamic_pointer_cast">dynamic_pointer_cast</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>dynamic_cast<T*>(p)</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U> std::shared_ptr<T>
|
|
dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>std::dynamic_pointer_cast<T>(p)</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U> std::unique_ptr<T>
|
|
dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>The expression <code>static_cast<T*>((U*)0)</code> must be well-formed.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>T</code> must have a virtual destructor.</p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>When <code>dynamic_cast<typename std::unique_ptr<T>::element_type*>(p.get())</code>
|
|
returns a non-zero value, <code>std::unique_ptr<T>(dynamic_cast<typename
|
|
std::unique_ptr<T>::element_type*>(p.release()));</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise, <code>std::unique_ptr<T>()</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="pointer_cast_const_pointer_cast">const_pointer_cast</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U> T* const_pointer_cast(U* p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>const_cast<T*>(p)</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U> std::shared_ptr<T>
|
|
const_pointer_cast(const std::shared_ptr<U>& p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>std::const_pointer_cast<T>(p)</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U> std::unique_ptr<T>
|
|
const_pointer_cast(std::unique_ptr<U>&& p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p>The expression <code>const_cast<T*>((U*)0)</code> must be well-formed.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>std::unique_ptr<T>(const_cast<typename
|
|
std::unique_ptr<T>::element_type*>(p.release()))</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="pointer_cast_reinterpret_pointer_cast">reinterpret_pointer_cast</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>reinterpret_cast<T*>(p)</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U> std::shared_ptr<T>
|
|
reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>std::reinterpret_pointer_cast<T>(p)</code></p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T, class U> std::unique_ptr<T>
|
|
reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p>The expression <code>reinterpret_cast<T*>((U*)0)</code> must be well-formed.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>std::unique_ptr<T>(reinterpret_cast<typename
|
|
std::unique_ptr<T>::element_type*>(p.release()))</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="pointer_cast_example">Example</h3>
|
|
<div class="paragraph">
|
|
<p>The following example demonstrates how the generic pointer casts help us
|
|
create pointer independent code.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>#include <boost/pointer_cast.hpp>
|
|
#include <boost/shared_ptr.hpp>
|
|
|
|
class base {
|
|
public:
|
|
virtual ~base() { }
|
|
};
|
|
|
|
class derived : public base { };
|
|
|
|
template<class Ptr>
|
|
void check_if_it_is_derived(const Ptr& ptr)
|
|
{
|
|
assert(boost::dynamic_pointer_cast<derived>(ptr) != 0);
|
|
}
|
|
|
|
int main()
|
|
{
|
|
base* ptr = new derived;
|
|
boost::shared_ptr<base> sptr(new derived);
|
|
|
|
check_if_it_is_derived(ptr);
|
|
check_if_it_is_derived(sptr);
|
|
|
|
delete ptr;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="pointer_to_other">pointer_to_other</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="pointer_to_other_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The <code>pointer_to_other</code> utility provides a way, given a source pointer type, to obtain a pointer of the same type
|
|
to another pointee type.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>There is test/example code in <a href="../../test/pointer_to_other_test.cpp">pointer_to_other_test.cpp</a>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="pointer_to_other_rationale">Rationale</h3>
|
|
<div class="paragraph">
|
|
<p>When building pointer independent classes, like memory managers, allocators, or containers, there is often a need to
|
|
define pointers generically, so that if a template parameter represents a pointer (for example, a raw or smart pointer
|
|
to an <code>int</code>), we can define another pointer of the same type to another pointee (a raw or smart pointer to a <code>float</code>.)</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template <class IntPtr> class FloatPointerHolder
|
|
{
|
|
// Let's define a pointer to a float
|
|
|
|
typedef typename boost::pointer_to_other
|
|
<IntPtr, float>::type float_ptr_t;
|
|
|
|
float_ptr_t float_ptr;
|
|
};</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="pointer_to_other_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>pointer_to_other</code> is defined in <code><boost/smart_ptr/pointer_to_other.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
|
|
template<class T, class U> struct pointer_to_other;
|
|
|
|
template<class T, class U,
|
|
template <class> class Sp>
|
|
struct pointer_to_other< Sp<T>, U >
|
|
{
|
|
typedef Sp<U> type;
|
|
};
|
|
|
|
template<class T, class T2, class U,
|
|
template <class, class> class Sp>
|
|
struct pointer_to_other< Sp<T, T2>, U >
|
|
{
|
|
typedef Sp<U, T2> type;
|
|
};
|
|
|
|
template<class T, class T2, class T3, class U,
|
|
template <class, class, class> class Sp>
|
|
struct pointer_to_other< Sp<T, T2, T3>, U >
|
|
{
|
|
typedef Sp<U, T2, T3> type;
|
|
};
|
|
|
|
template<class T, class U>
|
|
struct pointer_to_other< T*, U >
|
|
{
|
|
typedef U* type;
|
|
};
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If these definitions are not correct for a specific smart pointer, we can define a specialization of <code>pointer_to_other</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="pointer_to_other_example">Example</h3>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>// Let's define a memory allocator that can
|
|
// work with raw and smart pointers
|
|
|
|
#include <boost/pointer_to_other.hpp>
|
|
|
|
template <class VoidPtr>
|
|
class memory_allocator
|
|
{
|
|
// Predefine a memory_block
|
|
|
|
struct block;
|
|
|
|
// Define a pointer to a memory_block from a void pointer
|
|
// If VoidPtr is void *, block_ptr_t is block*
|
|
// If VoidPtr is smart_ptr<void>, block_ptr_t is smart_ptr<block>
|
|
|
|
typedef typename boost::pointer_to_other
|
|
<VoidPtr, block>::type block_ptr_t;
|
|
|
|
struct block
|
|
{
|
|
std::size_t size;
|
|
block_ptr_t next_block;
|
|
};
|
|
|
|
block_ptr_t free_blocks;
|
|
};</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As we can see, using <code>pointer_to_other</code> we can create pointer independent code.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="atomic_shared_ptr">atomic_shared_ptr</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="atomic_shared_ptr_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The class template <code>atomic_shared_ptr<T></code> implements the interface of <code>std::atomic</code>
|
|
for a contained value of type <code>shared_ptr<T></code>. Concurrent access to <code>atomic_shared_ptr</code>
|
|
is not a data race.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="atomic_shared_ptr_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>atomic_shared_ptr</code> is defined in <code><boost/smart_ptr/atomic_shared_ptr.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
|
|
template<class T> class atomic_shared_ptr {
|
|
private:
|
|
|
|
shared_ptr<T> p_; // exposition only
|
|
|
|
atomic_shared_ptr(const atomic_shared_ptr&) = delete;
|
|
atomic_shared_ptr& operator=(const atomic_shared_ptr&) = delete;
|
|
|
|
public:
|
|
|
|
constexpr atomic_shared_ptr() noexcept;
|
|
atomic_shared_ptr( shared_ptr<T> p ) noexcept;
|
|
|
|
atomic_shared_ptr& operator=( shared_ptr<T> r ) noexcept;
|
|
|
|
bool is_lock_free() const noexcept;
|
|
|
|
shared_ptr<T> load( int = 0 ) const noexcept;
|
|
operator shared_ptr<T>() const noexcept;
|
|
|
|
void store( shared_ptr<T> r, int = 0 ) noexcept;
|
|
|
|
shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) noexcept;
|
|
|
|
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
|
|
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
|
|
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
|
|
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
|
|
|
|
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
|
|
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
|
|
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
|
|
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
|
|
};
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="atomic_shared_ptr_members">Members</h3>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>constexpr atomic_shared_ptr() noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Default-initializes <code>p_</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>atomic_shared_ptr( shared_ptr<T> p ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Initializes <code>p_</code> to <code>p</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>atomic_shared_ptr& operator=( shared_ptr<T> r ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p><code>p_.swap(r)</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>*this</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>bool is_lock_free() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>false</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
This implementation is not lock-free.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr<T> load( int = 0 ) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>operator shared_ptr<T>() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>p_</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
The <code>int</code> argument is intended to be of type <code>memory_order</code>, but is ignored.
|
|
This implementation is lock-based and therefore always sequentially consistent.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>void store( shared_ptr<T> r, int = 0 ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p><code>p_.swap(r)</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p><code>p_.swap(r)</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>The old value of <code>p_</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>If <code>p_</code> is equivalent to <code>v</code>, assigns <code>w</code> to <code>p_</code>, otherwise assigns <code>p_</code> to <code>v</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>true</code> if <code>p_</code> was equivalent to <code>v</code>, <code>false</code> otherwise.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Remarks</dt>
|
|
<dd>
|
|
<p>Two <code>shared_ptr</code> instances are equivalent if they store the same pointer value and <em>share ownership</em>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>If <code>p_</code> is equivalent to <code>v</code>, assigns <code>std::move(w)</code> to <code>p_</code>, otherwise assigns <code>p_</code> to <code>v</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>true</code> if <code>p_</code> was equivalent to <code>v</code>, <code>false</code> otherwise.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Remarks</dt>
|
|
<dd>
|
|
<p>The old value of <code>w</code> is not preserved in either case.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="owner_less">owner_less</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="owner_less_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p><code>owner_less<T></code> is a helper function object that compares two smart
|
|
pointer objects using <code>owner_before</code>. It is only provided for compatibility
|
|
with C++11 and corresponds to the standard component of the same name.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When using Boost smart pointers, the use of <code>owner_less</code> is unnecessary, as
|
|
the supplied <code>operator<</code> overloads (and, correspondingly, <code>std::less</code>) return
|
|
the same result.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="owner_less_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>owner_less</code> is defined in <code><boost/smart_ptr/owner_less.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
|
|
template<class T = void> struct owner_less
|
|
{
|
|
typedef bool result_type;
|
|
typedef T first_argument_type;
|
|
typedef T second_argument_type;
|
|
|
|
template<class U, class V> bool operator()( U const & u, V const & v ) const noexcept;
|
|
};
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="owner_less_members">Members</h3>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class U, class V> bool operator()( U const & u, V const & v ) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>u.owner_before( v )</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="owner_equal_to">owner_equal_to</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="owner_equal_to_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p><code>owner_equal_to<T></code> is a helper function object that compares two smart
|
|
pointer objects using <code>owner_equals</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="owner_equal_to_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>owner_equal_to</code> is defined in <code><boost/smart_ptr/owner_equal_to.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
|
|
template<class T = void> struct owner_equal_to
|
|
{
|
|
typedef bool result_type;
|
|
typedef T first_argument_type;
|
|
typedef T second_argument_type;
|
|
|
|
template<class U, class V> bool operator()( U const & u, V const & v ) const noexcept;
|
|
};
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="owner_equal_to_members">Members</h3>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class U, class V> bool operator()( U const & u, V const & v ) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>u.owner_equals( v )</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="owner_hash">owner_hash</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="owner_hash_to_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p><code>owner_hash<T></code> is a helper function object that takes a smart pointer <code>p</code>
|
|
and returns <code>p.owner_hash_value()</code>. It’s useful for creating unordered
|
|
containers of <code>shared_ptr</code> that use ownership-based equality, instead of
|
|
the default pointer value equality. (It can be used with <code>weak_ptr</code> too,
|
|
but there’s no need, because <code>boost::hash</code> and <code>std::hash</code> for <code>weak_ptr</code>
|
|
already use ownership-based equality.)</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="owner_hash_to_example">Example</h3>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>std::unordered_set< boost::shared_ptr<void>,
|
|
boost::owner_hash< boost::shared_ptr<void> >,
|
|
boost::owner_equal_to< boost::shared_ptr<void> > > set;</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="owner_hash_to_synopsis">Synopsis</h3>
|
|
<div class="paragraph">
|
|
<p><code>owner_hash</code> is defined in <code><boost/smart_ptr/owner_hash.hpp></code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
|
|
template<class T> struct owner_hash
|
|
{
|
|
typedef std::size_t result_type;
|
|
typedef T argument_type;
|
|
|
|
std::size_t operator()( T const & p ) const noexcept;
|
|
};
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="owner_hash_to_members">Members</h3>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>std::size_t operator()( T const & p ) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>p.owner_hash_value()</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="techniques">Appendix A: Smart Pointer Programming Techniques</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="techniques_incomplete">Using incomplete classes for implementation hiding</h3>
|
|
<div class="paragraph">
|
|
<p>A proven technique (that works in C, too) for separating interface from implementation is to use a pointer to an incomplete class as an opaque handle:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>class FILE;
|
|
|
|
FILE * fopen(char const * name, char const * mode);
|
|
void fread(FILE * f, void * data, size_t size);
|
|
void fclose(FILE * f);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It is possible to express the above interface using <code>shared_ptr</code>, eliminating the need to manually call <code>fclose</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>class FILE;
|
|
|
|
shared_ptr<FILE> fopen(char const * name, char const * mode);
|
|
void fread(shared_ptr<FILE> f, void * data, size_t size);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This technique relies on <code>shared_ptr</code>’s ability to execute a custom deleter, eliminating the explicit call to <code>fclose</code>, and on the fact that <code>shared_ptr<X></code> can be copied and destroyed when <code>X</code> is incomplete.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_the_pimpl_idiom">The "Pimpl" idiom</h3>
|
|
<div class="paragraph">
|
|
<p>A C++ specific variation of the incomplete class pattern is the "Pimpl" idiom. The incomplete class is not exposed to the user; it is hidden behind a forwarding facade. <code>shared_ptr</code> can be used to implement a "Pimpl":</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>// file.hpp:
|
|
|
|
class file
|
|
{
|
|
private:
|
|
|
|
class impl;
|
|
shared_ptr<impl> pimpl_;
|
|
|
|
public:
|
|
|
|
file(char const * name, char const * mode);
|
|
|
|
// compiler generated members are fine and useful
|
|
|
|
void read(void * data, size_t size);
|
|
};
|
|
|
|
// file.cpp:
|
|
|
|
#include "file.hpp"
|
|
|
|
class file::impl
|
|
{
|
|
private:
|
|
|
|
impl(impl const &);
|
|
impl & operator=(impl const &);
|
|
|
|
// private data
|
|
|
|
public:
|
|
|
|
impl(char const * name, char const * mode) { ... }
|
|
~impl() { ... }
|
|
void read(void * data, size_t size) { ... }
|
|
};
|
|
|
|
file::file(char const * name, char const * mode): pimpl_(new impl(name, mode))
|
|
{
|
|
}
|
|
|
|
void file::read(void * data, size_t size)
|
|
{
|
|
pimpl_->read(data, size);
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The key thing to note here is that the compiler-generated copy constructor, assignment operator, and destructor all have a sensible meaning. As a result, <code>file</code> is <code>CopyConstructible</code> and <code>Assignable</code>, allowing its use in standard containers.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_using_abstract_classes_for_implementation_hiding">Using abstract classes for implementation hiding</h3>
|
|
<div class="paragraph">
|
|
<p>Another widely used C++ idiom for separating inteface and implementation is to use abstract base classes and factory functions.
|
|
The abstract classes are sometimes called "interfaces" and the pattern is known as "interface-based programming". Again,
|
|
<code>shared_ptr</code> can be used as the return type of the factory functions:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>// X.hpp:
|
|
|
|
class X
|
|
{
|
|
public:
|
|
|
|
virtual void f() = 0;
|
|
virtual void g() = 0;
|
|
|
|
protected:
|
|
|
|
~X() {}
|
|
};
|
|
|
|
shared_ptr<X> createX();
|
|
|
|
// X.cpp:
|
|
|
|
class X_impl: public X
|
|
{
|
|
private:
|
|
|
|
X_impl(X_impl const &);
|
|
X_impl & operator=(X_impl const &);
|
|
|
|
public:
|
|
|
|
virtual void f()
|
|
{
|
|
// ...
|
|
}
|
|
|
|
virtual void g()
|
|
{
|
|
// ...
|
|
}
|
|
};
|
|
|
|
shared_ptr<X> createX()
|
|
{
|
|
shared_ptr<X> px(new X_impl);
|
|
return px;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A key property of <code>shared_ptr</code> is that the allocation, construction, deallocation, and destruction details are captured at the point of construction, inside the factory function.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Note the protected and nonvirtual destructor in the example above. The client code cannot, and does not need to, delete a pointer to <code>X</code>; the <code>shared_ptr<X></code> instance returned from <code>createX</code> will correctly call <code>~X_impl</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_preventing_delete_px_get">Preventing <code>delete px.get()</code></h3>
|
|
<div class="paragraph">
|
|
<p>It is often desirable to prevent client code from deleting a pointer that is being managed by <code>shared_ptr</code>. The previous technique showed one possible approach, using a protected destructor. Another alternative is to use a private deleter:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>class X
|
|
{
|
|
private:
|
|
|
|
~X();
|
|
|
|
class deleter;
|
|
friend class deleter;
|
|
|
|
class deleter
|
|
{
|
|
public:
|
|
|
|
void operator()(X * p) { delete p; }
|
|
};
|
|
|
|
public:
|
|
|
|
static shared_ptr<X> create()
|
|
{
|
|
shared_ptr<X> px(new X, X::deleter());
|
|
return px;
|
|
}
|
|
};</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_encapsulating_allocation_details_wrapping_factory_functions">Encapsulating allocation details, wrapping factory functions</h3>
|
|
<div class="paragraph">
|
|
<p><code>shared_ptr</code> can be used in creating C++ wrappers over existing C style library interfaces that return raw pointers from their factory functions
|
|
to encapsulate allocation details. As an example, consider this interface, where <code>CreateX</code> might allocate <code>X</code> from its own private heap, <code>~X</code> may
|
|
be inaccessible, or <code>X</code> may be incomplete:</p>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>X * CreateX();
|
|
void DestroyX(X *);</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The only way to reliably destroy a pointer returned by <code>CreateX</code> is to call <code>DestroyX</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is how a <code>shared_ptr</code>-based wrapper may look like:</p>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>shared_ptr<X> createX()
|
|
{
|
|
shared_ptr<X> px(CreateX(), DestroyX);
|
|
return px;
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Client code that calls <code>createX</code> still does not need to know how the object has been allocated, but now the destruction is automatic.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_static">Using a shared_ptr to hold a pointer to a statically allocated object</h3>
|
|
<div class="paragraph">
|
|
<p>Sometimes it is desirable to create a <code>shared_ptr</code> to an already existing object, so that the <code>shared_ptr</code> does not attempt to destroy the
|
|
object when there are no more references left. As an example, the factory function:</p>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>shared_ptr<X> createX();</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>in certain situations may need to return a pointer to a statically allocated <code>X</code> instance.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The solution is to use a custom deleter that does nothing:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>struct null_deleter
|
|
{
|
|
void operator()(void const *) const
|
|
{
|
|
}
|
|
};
|
|
|
|
static X x;
|
|
|
|
shared_ptr<X> createX()
|
|
{
|
|
shared_ptr<X> px(&x, null_deleter());
|
|
return px;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The same technique works for any object known to outlive the pointer.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_using_a_shared_ptr_to_hold_a_pointer_to_a_com_object">Using a shared_ptr to hold a pointer to a COM Object</h3>
|
|
<div class="paragraph">
|
|
<p>Background: COM objects have an embedded reference count and two member functions that manipulate it. <code>AddRef()</code> increments the count.
|
|
<code>Release()</code> decrements the count and destroys itself when the count drops to zero.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It is possible to hold a pointer to a COM object in a <code>shared_ptr</code>:</p>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)
|
|
{
|
|
p->AddRef();
|
|
shared_ptr<IWhatever> pw(p, mem_fn(&IWhatever::Release));
|
|
return pw;
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Note, however, that <code>shared_ptr</code> copies created from <code>pw</code> will not "register" in the embedded count of the COM object;
|
|
they will share the single reference created in <code>make_shared_from_COM</code>. Weak pointers created from <code>pw</code> will be invalidated when the last
|
|
<code>shared_ptr</code> is destroyed, regardless of whether the COM object itself is still alive.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As <a href="../../../../libs/bind/mem_fn.html#Q3">explained</a> in the <code>mem_fn</code> documentation, you need to <code>#define BOOST_MEM_FN_ENABLE_STDCALL</code> first.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_intrusive">Using a shared_ptr to hold a pointer to an object with an embedded reference count</h3>
|
|
<div class="paragraph">
|
|
<p>This is a generalization of the above technique. The example assumes that the object implements the two functions required by <code><a href="#intrusive_ptr">intrusive_ptr</a></code>,
|
|
<code>intrusive_ptr_add_ref</code> and <code>intrusive_ptr_release</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> struct intrusive_deleter
|
|
{
|
|
void operator()(T * p)
|
|
{
|
|
if(p) intrusive_ptr_release(p);
|
|
}
|
|
};
|
|
|
|
shared_ptr<X> make_shared_from_intrusive(X * p)
|
|
{
|
|
if(p) intrusive_ptr_add_ref(p);
|
|
shared_ptr<X> px(p, intrusive_deleter<X>());
|
|
return px;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_using_a_shared_ptr_to_hold_another_shared_ownership_smart_pointer">Using a shared_ptr to hold another shared ownership smart pointer</h3>
|
|
<div class="paragraph">
|
|
<p>One of the design goals of <code>shared_ptr</code> is to be used in library interfaces. It is possible to encounter a situation where a library takes a
|
|
<code>shared_ptr</code> argument, but the object at hand is being managed by a different reference counted or linked smart pointer.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It is possible to exploit <code>shared_ptr</code>’s custom deleter feature to wrap this existing smart pointer behind a <code>shared_ptr</code> facade:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class P> struct smart_pointer_deleter
|
|
{
|
|
private:
|
|
|
|
P p_;
|
|
|
|
public:
|
|
|
|
smart_pointer_deleter(P const & p): p_(p)
|
|
{
|
|
}
|
|
|
|
void operator()(void const *)
|
|
{
|
|
p_.reset();
|
|
}
|
|
|
|
P const & get() const
|
|
{
|
|
return p_;
|
|
}
|
|
};
|
|
|
|
shared_ptr<X> make_shared_from_another(another_ptr<X> qx)
|
|
{
|
|
shared_ptr<X> px(qx.get(), smart_pointer_deleter< another_ptr<X> >(qx));
|
|
return px;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>One subtle point is that deleters are not allowed to throw exceptions, and the above example as written assumes that <code>p_.reset()</code> doesn’t throw.
|
|
If this is not the case, <code>p_.reset();</code> should be wrapped in a <code>try {} catch(…​) {}</code> block that ignores exceptions. In the (usually unlikely) event
|
|
when an exception is thrown and ignored, <code>p_</code> will be released when the lifetime of the deleter ends. This happens when all references, including
|
|
weak pointers, are destroyed or reset.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Another twist is that it is possible, given the above <code>shared_ptr</code> instance, to recover the original smart pointer, using <code><a href="#shared_ptr_get_deleter">get_deleter</a></code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>void extract_another_from_shared(shared_ptr<X> px)
|
|
{
|
|
typedef smart_pointer_deleter< another_ptr<X> > deleter;
|
|
|
|
if(deleter const * pd = get_deleter<deleter>(px))
|
|
{
|
|
another_ptr<X> qx = pd->get();
|
|
}
|
|
else
|
|
{
|
|
// not one of ours
|
|
}
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_from_raw">Obtaining a shared_ptr from a raw pointer</h3>
|
|
<div class="paragraph">
|
|
<p>Sometimes it is necessary to obtain a <code>shared_ptr</code> given a raw pointer to an object that is already managed by another <code>shared_ptr</code> instance. Example:</p>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>void f(X * p)
|
|
{
|
|
shared_ptr<X> px(???);
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Inside <code>f</code>, we’d like to create a <code>shared_ptr</code> to <code>*p</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In the general case, this problem has no solution. One approach is to modify <code>f</code> to take a <code>shared_ptr</code>, if possible:</p>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>void f(shared_ptr<X> px);</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The same transformation can be used for nonvirtual member functions, to convert the implicit <code>this</code>:</p>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>void X::f(int m);</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>would become a free function with a <code>shared_ptr</code> first argument:</p>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>void f(shared_ptr<X> this_, int m);</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If <code>f</code> cannot be changed, but <code>X</code> uses intrusive counting, use <code><a href="#techniques_intrusive">make_shared_from_intrusive</a></code> described above. Or, if it’s known that the <code>shared_ptr</code> created in <code>f</code> will never outlive the object, use <a href="#techniques_static">a null deleter</a>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_obtaining_a_shared_ptr_weak_ptr_to_this_in_a_constructor">Obtaining a shared_ptr (weak_ptr) to this in a constructor</h3>
|
|
<div class="paragraph">
|
|
<p>Some designs require objects to register themselves on construction with a central authority. When the registration routines take a <code>shared_ptr</code>, this leads to the question how could a constructor obtain a <code>shared_ptr</code> to <code>this</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>class X
|
|
{
|
|
public:
|
|
|
|
X()
|
|
{
|
|
shared_ptr<X> this_(???);
|
|
}
|
|
};</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In the general case, the problem cannot be solved. The <code>X</code> instance being constructed can be an automatic variable or a static variable; it can be created on the heap:</p>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>shared_ptr<X> px(new X);</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>but at construction time, <code>px</code> does not exist yet, and it is impossible to create another <code>shared_ptr</code> instance that shares ownership with it.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Depending on context, if the inner <code>shared_ptr this_</code> doesn’t need to keep the object alive, use a <code>null_deleter</code> as explained <a href="#techniques_static">here</a> and <a href="#techniques_weak_without_shared">here</a>.
|
|
If <code>X</code> is supposed to always live on the heap, and be managed by a <code>shared_ptr</code>, use a static factory function:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>class X
|
|
{
|
|
private:
|
|
|
|
X() { ... }
|
|
|
|
public:
|
|
|
|
static shared_ptr<X> create()
|
|
{
|
|
shared_ptr<X> px(new X);
|
|
// use px as 'this_'
|
|
return px;
|
|
}
|
|
};</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_obtaining_a_shared_ptr_to_this">Obtaining a shared_ptr to this</h3>
|
|
<div class="paragraph">
|
|
<p>Sometimes it is needed to obtain a <code>shared_ptr</code> from <code>this</code> in a virtual member function under the assumption that <code>this</code> is already managed by a <code>shared_ptr</code>.
|
|
The transformations <a href="#techniques_from_raw">described in the previous technique</a> cannot be applied.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A typical example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>class X
|
|
{
|
|
public:
|
|
|
|
virtual void f() = 0;
|
|
|
|
protected:
|
|
|
|
~X() {}
|
|
};
|
|
|
|
class Y
|
|
{
|
|
public:
|
|
|
|
virtual shared_ptr<X> getX() = 0;
|
|
|
|
protected:
|
|
|
|
~Y() {}
|
|
};
|
|
|
|
// --
|
|
|
|
class impl: public X, public Y
|
|
{
|
|
public:
|
|
|
|
impl() { ... }
|
|
|
|
virtual void f() { ... }
|
|
|
|
virtual shared_ptr<X> getX()
|
|
{
|
|
shared_ptr<X> px(???);
|
|
return px;
|
|
}
|
|
};</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The solution is to keep a weak pointer to <code>this</code> as a member in <code>impl</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>class impl: public X, public Y
|
|
{
|
|
private:
|
|
|
|
weak_ptr<impl> weak_this;
|
|
|
|
impl(impl const &);
|
|
impl & operator=(impl const &);
|
|
|
|
impl() { ... }
|
|
|
|
public:
|
|
|
|
static shared_ptr<impl> create()
|
|
{
|
|
shared_ptr<impl> pi(new impl);
|
|
pi->weak_this = pi;
|
|
return pi;
|
|
}
|
|
|
|
virtual void f() { ... }
|
|
|
|
virtual shared_ptr<X> getX()
|
|
{
|
|
shared_ptr<X> px(weak_this);
|
|
return px;
|
|
}
|
|
};</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The library now includes a helper class template <code><a href="#enable_shared_from_this">enable_shared_from_this</a></code> that can be used to encapsulate the solution:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>class impl: public X, public Y, public enable_shared_from_this<impl>
|
|
{
|
|
public:
|
|
|
|
impl(impl const &);
|
|
impl & operator=(impl const &);
|
|
|
|
public:
|
|
|
|
virtual void f() { ... }
|
|
|
|
virtual shared_ptr<X> getX()
|
|
{
|
|
return shared_from_this();
|
|
}
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Note that you no longer need to manually initialize the <code>weak_ptr</code> member in <code>enable_shared_from_this</code>. Constructing a <code>shared_ptr</code> to <code>impl</code> takes care of that.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_using_shared_ptr_as_a_smart_counted_handle">Using shared_ptr as a smart counted handle</h3>
|
|
<div class="paragraph">
|
|
<p>Some library interfaces use opaque handles, a variation of the <a href="#techniques_incomplete">incomplete class technique</a> described above. An example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>typedef void * HANDLE;
|
|
|
|
HANDLE CreateProcess();
|
|
void CloseHandle(HANDLE);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Instead of a raw pointer, it is possible to use <code>shared_ptr</code> as the handle and get reference counting and automatic resource management for free:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>typedef shared_ptr<void> handle;
|
|
|
|
handle createProcess()
|
|
{
|
|
shared_ptr<void> pv(CreateProcess(), CloseHandle);
|
|
return pv;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_using_shared_ptr_to_execute_code_on_block_exit">Using shared_ptr to execute code on block exit</h3>
|
|
<div class="paragraph">
|
|
<p><code>shared_ptr<void></code> can automatically execute cleanup code when control leaves a scope.</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Executing <code>f(p)</code>, where <code>p</code> is a pointer:</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr<void> guard(p, f);</code></pre>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>Executing arbitrary code: <code>f(x, y)</code>:</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));</code></pre>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_using_shared_ptrvoid_to_hold_an_arbitrary_object">Using shared_ptr<void> to hold an arbitrary object</h3>
|
|
<div class="paragraph">
|
|
<p><code>shared_ptr<void></code> can act as a generic object pointer similar to <code>void*</code>. When a <code>shared_ptr<void></code> instance constructed as:</p>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>shared_ptr<void> pv(new X);</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>is destroyed, it will correctly dispose of the <code>X</code> object by executing <code>~X</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This propery can be used in much the same manner as a raw <code>void*</code> is used to temporarily strip type information from an object pointer.
|
|
A <code>shared_ptr<void></code> can later be cast back to the correct type by using <code><a href="#shared_ptr_static_pointer_cast">static_pointer_cast</a></code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_associating_arbitrary_data_with_heterogeneous_shared_ptr_instances">Associating arbitrary data with heterogeneous <code>shared_ptr</code> instances</h3>
|
|
<div class="paragraph">
|
|
<p><code>shared_ptr</code> and <code>weak_ptr</code> support <code>operator<</code> comparisons required by standard associative containers such as <code>std::map</code>. This can be
|
|
used to non-intrusively associate arbitrary data with objects managed by <code>shared_ptr</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>typedef int Data;
|
|
|
|
std::map<shared_ptr<void>, Data> userData;
|
|
// or std::map<weak_ptr<void>, Data> userData; to not affect the lifetime
|
|
|
|
shared_ptr<X> px(new X);
|
|
shared_ptr<int> pi(new int(3));
|
|
|
|
userData[px] = 42;
|
|
userData[pi] = 91;</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_using_shared_ptr_as_a_copyconstructible_mutex_lock">Using <code>shared_ptr</code> as a <code>CopyConstructible</code> mutex lock</h3>
|
|
<div class="paragraph">
|
|
<p>Sometimes it’s necessary to return a mutex lock from a function, and a noncopyable lock cannot be returned by value. It is possible to use <code>shared_ptr</code> as a mutex lock:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>class mutex
|
|
{
|
|
public:
|
|
|
|
void lock();
|
|
void unlock();
|
|
};
|
|
|
|
shared_ptr<mutex> lock(mutex & m)
|
|
{
|
|
m.lock();
|
|
return shared_ptr<mutex>(&m, mem_fn(&mutex::unlock));
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Better yet, the <code>shared_ptr</code> instance acting as a lock can be encapsulated in a dedicated <code>shared_lock</code> class:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>class shared_lock
|
|
{
|
|
private:
|
|
|
|
shared_ptr<void> pv;
|
|
|
|
public:
|
|
|
|
template<class Mutex> explicit shared_lock(Mutex & m): pv((m.lock(), &m), mem_fn(&Mutex::unlock)) {}
|
|
};</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>shared_lock</code> can now be used as:</p>
|
|
</div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre>shared_lock lock(m);</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Note that <code>shared_lock</code> is not templated on the mutex type, thanks to <code>shared_ptr<void></code>’s ability to hide type information.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_using_shared_ptr_to_wrap_member_function_calls">Using shared_ptr to wrap member function calls</h3>
|
|
<div class="paragraph">
|
|
<p><code>shared_ptr</code> implements the ownership semantics required from the <code>Wrap/CallProxy</code> scheme described in Bjarne Stroustrup’s article
|
|
"Wrapping C++ Member Function Calls" (available online at <a href="http://www.stroustrup.com/wrapper.pdf" class="bare">http://www.stroustrup.com/wrapper.pdf</a>). An implementation is given below:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> class pointer
|
|
{
|
|
private:
|
|
|
|
T * p_;
|
|
|
|
public:
|
|
|
|
explicit pointer(T * p): p_(p)
|
|
{
|
|
}
|
|
|
|
shared_ptr<T> operator->() const
|
|
{
|
|
p_->prefix();
|
|
return shared_ptr<T>(p_, mem_fn(&T::suffix));
|
|
}
|
|
};
|
|
|
|
class X
|
|
{
|
|
private:
|
|
|
|
void prefix();
|
|
void suffix();
|
|
friend class pointer<X>;
|
|
|
|
public:
|
|
|
|
void f();
|
|
void g();
|
|
};
|
|
|
|
int main()
|
|
{
|
|
X x;
|
|
|
|
pointer<X> px(&x);
|
|
|
|
px->f();
|
|
px->g();
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_delayed_deallocation">Delayed deallocation</h3>
|
|
<div class="paragraph">
|
|
<p>In some situations, a single <code>px.reset()</code> can trigger an expensive deallocation in a performance-critical region:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>class X; // ~X is expensive
|
|
|
|
class Y
|
|
{
|
|
shared_ptr<X> px;
|
|
|
|
public:
|
|
|
|
void f()
|
|
{
|
|
px.reset();
|
|
}
|
|
};</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The solution is to postpone the potential deallocation by moving <code>px</code> to a dedicated free list that can be periodically emptied when performance and response times are not an issue:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>vector< shared_ptr<void> > free_list;
|
|
|
|
class Y
|
|
{
|
|
shared_ptr<X> px;
|
|
|
|
public:
|
|
|
|
void f()
|
|
{
|
|
free_list.push_back(px);
|
|
px.reset();
|
|
}
|
|
};
|
|
|
|
// periodically invoke free_list.clear() when convenient</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Another variation is to move the free list logic to the construction point by using a delayed deleter:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>struct delayed_deleter
|
|
{
|
|
template<class T> void operator()(T * p)
|
|
{
|
|
try
|
|
{
|
|
shared_ptr<void> pv(p);
|
|
free_list.push_back(pv);
|
|
}
|
|
catch(...)
|
|
{
|
|
}
|
|
}
|
|
};</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="techniques_weak_without_shared">Weak pointers to objects not managed by a shared_ptr</h3>
|
|
<div class="paragraph">
|
|
<p>Make the object hold a <code>shared_ptr</code> to itself, using a <code>null_deleter</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>class X
|
|
{
|
|
private:
|
|
|
|
shared_ptr<X> this_;
|
|
int i_;
|
|
|
|
public:
|
|
|
|
explicit X(int i): this_(this, null_deleter()), i_(i)
|
|
{
|
|
}
|
|
|
|
// repeat in all constructors (including the copy constructor!)
|
|
|
|
X(X const & rhs): this_(this, null_deleter()), i_(rhs.i_)
|
|
{
|
|
}
|
|
|
|
// do not forget to not assign this_ in the copy assignment
|
|
|
|
X & operator=(X const & rhs)
|
|
{
|
|
i_ = rhs.i_;
|
|
}
|
|
|
|
weak_ptr<X> get_weak_ptr() const { return this_; }
|
|
};</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When the object’s lifetime ends, <code>X::this_</code> will be destroyed, and all weak pointers will automatically expire.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="history">Appendix B: History and Acknowledgments</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="history_summer_1994">Summer 1994</h3>
|
|
<div class="paragraph">
|
|
<p>Greg Colvin <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1994/N0555.pdf">proposed</a>
|
|
to the C++ Standards Committee classes named <code>auto_ptr</code> and <code>counted_ptr</code> which were very
|
|
similar to what we now call <code>scoped_ptr</code> and <code>shared_ptr</code>. In one of the very few cases
|
|
where the Library Working Group’s recommendations were not followed by the full committee,
|
|
<code>counted_ptr</code> was rejected and surprising transfer-of-ownership semantics were added to <code>auto_ptr</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="history_october_1998">October 1998</h3>
|
|
<div class="paragraph">
|
|
<p>Beman Dawes proposed reviving the original semantics under the names <code>safe_ptr</code> and <code>counted_ptr</code>,
|
|
meeting of Per Andersson, Matt Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis,
|
|
Dietmar Kühl, Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new class
|
|
names were finalized, it was decided that there was no need to exactly follow the <code>std::auto_ptr</code>
|
|
interface, and various function signatures and semantics were finalized.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Over the next three months, several implementations were considered for <code>shared_ptr</code>, and discussed
|
|
on the <a href="http://www.boost.org/">boost.org</a> mailing list. The implementation questions revolved around
|
|
the reference count which must be kept, either attached to the pointed to object, or detached elsewhere.
|
|
Each of those variants have themselves two major variants:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Direct detached: the <code>shared_ptr</code> contains a pointer to the object, and a pointer to the count.</p>
|
|
</li>
|
|
<li>
|
|
<p>Indirect detached: the <code>shared_ptr</code> contains a pointer to a helper object, which in turn contains a pointer to the object and the count.</p>
|
|
</li>
|
|
<li>
|
|
<p>Embedded attached: the count is a member of the object pointed to.</p>
|
|
</li>
|
|
<li>
|
|
<p>Placement attached: the count is attached via operator new manipulations.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Each implementation technique has advantages and disadvantages. We went so far as to run various timings
|
|
of the direct and indirect approaches, and found that at least on Intel Pentium chips there was very little
|
|
measurable difference. Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar Kühl
|
|
suggested an elegant partial template specialization technique to allow users to choose which implementation
|
|
they preferred, and that was also experimented with.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage users", and in the end we choose
|
|
to supply only the direct implementation.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="history_may_1999">May 1999</h3>
|
|
<div class="paragraph">
|
|
<p>In April and May, 1999, Valentin Bonnard and David Abrahams made a number of suggestions resulting in numerous improvements.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="history_september_1999">September 1999</h3>
|
|
<div class="paragraph">
|
|
<p>Luis Coelho provided <code>shared_ptr::swap</code> and <code>shared_array::swap</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="history_november_1999">November 1999</h3>
|
|
<div class="paragraph">
|
|
<p>Darin Adler provided <code>operator ==</code>, <code>operator !=</code>, and <code>std::swap</code> and <code>std::less</code> specializations for shared types.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="history_may_2001">May 2001</h3>
|
|
<div class="paragraph">
|
|
<p>Vladimir Prus suggested requiring a complete type on destruction. Refinement evolved in discussions including Dave Abrahams,
|
|
Greg Colvin, Beman Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and others.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="history_january_2002">January 2002</h3>
|
|
<div class="paragraph">
|
|
<p>Peter Dimov reworked all four classes, adding features, fixing bugs, splitting them into four separate headers, and adding
|
|
<code>weak_ptr</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="history_march_2003">March 2003</h3>
|
|
<div class="paragraph">
|
|
<p>Peter Dimov, Beman Dawes and Greg Colvin <a href="http://open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1450.html">proposed</a> <code>shared_ptr</code>
|
|
and <code>weak_ptr</code> for inclusion in the Standard Library via the first Library Technical Report (known as TR1). The proposal was
|
|
accepted and eventually went on to become a part of the C++ standard in its 2011 iteration.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="history_july_2007">July 2007</h3>
|
|
<div class="paragraph">
|
|
<p>Peter Dimov and Beman Dawes <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2351.htm">proposed</a> a number of enhancements
|
|
to <code>shared_ptr</code> as it was entering the working paper that eventually became the C++11 standard.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="history_november_2012">November 2012</h3>
|
|
<div class="paragraph">
|
|
<p>Glen Fernandes provided implementations of <code>make_shared</code> and <code>allocate_shared</code> for arrays. They achieve a single allocation
|
|
for an array that can be initialized with constructor arguments or initializer lists as well as overloads for default initialization
|
|
and no value initialization.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Peter Dimov aided this development by extending <code>shared_ptr</code> to support arrays via the syntax <code>shared_ptr<T[]></code> and <code>shared_ptr<T[N]></code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="history_april_2013">April 2013</h3>
|
|
<div class="paragraph">
|
|
<p>Peter Dimov <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3640.html">proposed</a> the extension of <code>shared_ptr</code> to support
|
|
arrays for inclusion into the standard, and it was accepted.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="history_february_2014">February 2014</h3>
|
|
<div class="paragraph">
|
|
<p>Glen Fernandes updated <code>make_shared</code> and <code>allocate_shared</code> to conform to the specification in C++ standard paper
|
|
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3870.html">N3870</a>, and implemented <code>make_unique</code> for arrays and objects.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Peter Dimov and Glen Fernandes updated the scalar and array implementations, respectively, to resolve C++ standard library defect 2070.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="history_february_2017">February 2017</h3>
|
|
<div class="paragraph">
|
|
<p>Glen Fernandes rewrote <code>allocate_shared</code> and <code>make_shared</code> for arrays for a more optimal and more maintainable implementation.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="history_june_2017">June 2017</h3>
|
|
<div class="paragraph">
|
|
<p>Peter Dimov and Glen Fernandes rewrote the documentation in Asciidoc format.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Peter Dimov added <code>atomic_shared_ptr</code> and <code>local_shared_ptr</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="history_august_2019">August 2019</h3>
|
|
<div class="paragraph">
|
|
<p>Glen Fernandes implemented <code>allocate_unique</code> for scalars and arrays.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="shared_array">Appendix C: shared_array (deprecated)</h2>
|
|
<div class="sectionbody">
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
This facility is deprecated because a <code>shared_ptr</code> to <code>T[]</code> or <code>T[N]</code>
|
|
is now available, and is superior in every regard.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="shared_array_description">Description</h3>
|
|
<div class="paragraph">
|
|
<p>The <code>shared_array</code> class template stores a pointer to a dynamically allocated
|
|
array. (Dynamically allocated array are allocated with the C++ <code>new[]</code>
|
|
expression.) The object pointed to is guaranteed to be deleted when the last
|
|
<code>shared_array</code> pointing to it is destroyed or reset.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Every <code>shared_array</code> meets the <em>CopyConstructible</em> and <em>Assignable</em>
|
|
requirements of the C++ Standard Library, and so can be used in standard
|
|
library containers. Comparison operators are supplied so that shared_array
|
|
works with the standard library’s associative containers.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Normally, a <code>shared_array</code> cannot correctly hold a pointer to an object that
|
|
has been allocated with the non-array form of <code>new</code>. See <code>shared_ptr</code> for that
|
|
usage.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Because the implementation uses reference counting, cycles of <code>shared_array</code>
|
|
instances will not be reclaimed. For example, if <code>main</code> holds a shared_array
|
|
to <code>A</code>, which directly or indirectly holds a shared_array back to <code>A</code>, the use
|
|
count of <code>A</code> will be 2. Destruction of the original <code>shared_array</code> will leave
|
|
<code>A</code> dangling with a use count of 1.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A <code>shared_ptr</code> to a <code>std::vector</code> is an alternative to a <code>shared_array</code> that
|
|
is a bit heavier duty but far more flexible.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The class template is parameterized on <code>T</code>, the type of the object pointed to.
|
|
<code>shared_array</code> and most of its member functions place no requirements on <code>T</code>;
|
|
it is allowed to be an incomplete type, or <code>void</code>. Member functions that do
|
|
place additional requirements (constructors, reset) are explicitly documented
|
|
below.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="shared_array_synopsis">Synopsis</h3>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>namespace boost {
|
|
|
|
template<class T> class shared_array {
|
|
public:
|
|
typedef T element_type;
|
|
|
|
explicit shared_array(T* p = 0);
|
|
template<class D> shared_array(T* p, D d);
|
|
shared_array(const shared_array& v) noexcept;
|
|
|
|
~shared_array() noexcept;
|
|
|
|
shared_array& operator=(const shared_array& v) noexcept;
|
|
|
|
void reset(T* p = 0);
|
|
template<class D> void reset(T* p, D d);
|
|
|
|
T& operator[](std::ptrdiff_t n) const noexcept;
|
|
T* get() const noexcept;
|
|
|
|
bool unique() const noexcept;
|
|
long use_count() const noexcept;
|
|
|
|
explicit operator bool() const noexcept;
|
|
|
|
void swap(shared_array<T>& v) noexcept;
|
|
};
|
|
|
|
template<class T> bool
|
|
operator==(const shared_array<T>& a, const shared_array<T>& b) noexcept;
|
|
template<class T> bool
|
|
operator!=(const shared_array<T>& a, const shared_array<T>& b) noexcept;
|
|
template<class T> bool
|
|
operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept;
|
|
|
|
template<class T>
|
|
void swap(shared_array<T>& a, shared_array<T>& b) noexcept;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="shared_array_members">Members</h3>
|
|
<div class="sect3">
|
|
<h4 id="shared_array_element_type">element_type</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>typedef T element_type;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Type</dt>
|
|
<dd>
|
|
<p>Provides the type of the stored pointer.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_array_constructors">Constructors</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>explicit shared_array(T* p = 0);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs a <code>shared_array</code>, storing a copy of <code>p</code>, which must be a
|
|
pointer to an array that was allocated via a C++ <code>new[]</code> expression or be 0.
|
|
Afterwards, the use count is 1 (even if <code>p == 0</code>; see <code>~shared_array</code>).</p>
|
|
</dd>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>T</code> is a complete type.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p><code>std::bad_alloc</code>. If an exception is thrown, <code>delete[] p</code> is called.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class D> shared_array(T* p, D d);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs a <code>shared_array</code>, storing a copy of <code>p</code> and of <code>d</code>.
|
|
Afterwards, the use count is 1. When the the time comes to delete the array
|
|
pointed to by <code>p</code>, the object <code>d</code> is used in the statement <code>d(p)</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Requires</dt>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p><code>T</code> is a complete type.</p>
|
|
</li>
|
|
<li>
|
|
<p>The copy constructor and destructor of <code>D</code> must not throw.</p>
|
|
</li>
|
|
<li>
|
|
<p>Invoking the object <code>d</code> with parameter <code>p</code> must not throw.</p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p><code>std::bad_alloc</code>. If an exception is thrown, <code>d(p)</code> is called.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_array(const shared_array& v) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs a <code>shared_array</code>, as if by storing a copy of the pointer
|
|
stored in <code>v</code>. Afterwards, the use count for all copies is 1 more than the
|
|
initial use count.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>T</code> is a complete type.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_array_destructor">Destructor</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>~shared_array() noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Decrements the use count. Then, if the use count is 0, deletes the
|
|
array pointed to by the stored pointer. Note that <code>delete[]</code> on a pointer with
|
|
a value of 0 is harmless.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_array_assignment">Assignment</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>shared_array& operator=(const shared_array& v) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs a new <code>shared_array</code> as described above, then replaces
|
|
this <code>shared_array</code> with the new one, destroying the replaced object.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>T</code> is a complete type.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>*this</code>.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_array_reset">reset</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>void reset(T* p = 0);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs a new <code>shared_array</code> as described above, then replaces
|
|
this <code>shared_array</code> with the new one, destroying the replaced object.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>T</code> is a complete type.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p><code>std::bad_alloc</code>. If an exception is thrown, <code>delete[] p</code> is called.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class D> void reset(T* p, D d);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Constructs a new <code>shared_array</code> as described above, then replaces
|
|
this <code>shared_array</code> with the new one, destroying the replaced object.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Requires</dt>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p><code>T</code> is a complete type.</p>
|
|
</li>
|
|
<li>
|
|
<p>The copy constructor of <code>D</code> must not throw.</p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Throws</dt>
|
|
<dd>
|
|
<p><code>std::bad_alloc</code>. If an exception is thrown, <code>d(p)</code> is called.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_array_indexing">Indexing</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>T& operator[](std::ptrdiff_t n) const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>A reference to element <code>n</code> of the array pointed to by the stored
|
|
pointer. Behavior is undefined and almost certainly undesirable if the stored
|
|
pointer is 0, or if <code>n</code> is less than 0 or is greater than or equal to the
|
|
number of elements in the array.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>T</code> is a complete type.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_array_get">get</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>T* get() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>The stored pointer.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_array_unique">unique</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>bool unique() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>true</code> if no other <code>shared_array</code> is sharing ownership of the
|
|
stored pointer, <code>false</code> otherwise.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_array_use_count">use_count</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>long use_count() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>The number of <code>shared_array</code> objects sharing ownership of the
|
|
stored pointer.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_array_conversions">Conversions</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>explicit operator bool() const noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>get() != 0</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>T</code> is a complete type.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_array_swap">swap</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>void swap(shared_array<T>& b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Effects</dt>
|
|
<dd>
|
|
<p>Exchanges the contents of the two smart pointers.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="shared_array_free_functions">Free Functions</h3>
|
|
<div class="sect3">
|
|
<h4 id="shared_array_comparison">Comparison</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> bool
|
|
operator==(const shared_array<T>& a, const shared_array<T>& b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> bool
|
|
operator!=(const shared_array<T>& a, const shared_array<T>& b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T> bool
|
|
operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p>The result of comparing the stored pointers of the two smart
|
|
pointers.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="admonitionblock note">
|
|
<table>
|
|
<tr>
|
|
<td class="icon">
|
|
<div class="title">Note</div>
|
|
</td>
|
|
<td class="content">
|
|
The <code>operator<</code> overload is provided to define an ordering so that
|
|
<code>shared_array</code> objects can be used in associative containers such as
|
|
<code>std::map</code>. The implementation uses <code>std::less<T*></code> to perform the comparison.
|
|
This ensures that the comparison is handled correctly, since the standard
|
|
mandates that relational operations on pointers are unspecified (5.9
|
|
[expr.rel] paragraph 2) but <code>std::less</code> on pointers is well-defined (20.3.3
|
|
[lib.comparisons] paragraph 8).
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="shared_array_swap_2">swap</h4>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="highlight"><code>template<class T>
|
|
void swap(shared_array<T>& a, shared_array<T>& b) noexcept;</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="ulist none">
|
|
<ul class="none">
|
|
<li>
|
|
<p></p>
|
|
<div class="dlist">
|
|
<dl>
|
|
<dt class="hdlist1">Returns</dt>
|
|
<dd>
|
|
<p><code>a.swap(b)</code>.</p>
|
|
</dd>
|
|
<dt class="hdlist1">Requires</dt>
|
|
<dd>
|
|
<p><code>T</code> is a complete type.</p>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="copyright">Appendix D: Copyright and License</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>This documentation is</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Copyright 1999 Greg Colvin</p>
|
|
</li>
|
|
<li>
|
|
<p>Copyright 1999 Beman Dawes</p>
|
|
</li>
|
|
<li>
|
|
<p>Copyright 2002 Darin Adler</p>
|
|
</li>
|
|
<li>
|
|
<p>Copyright 2003-2020 Peter Dimov</p>
|
|
</li>
|
|
<li>
|
|
<p>Copyright 2005, 2006 Ion Gaztañaga</p>
|
|
</li>
|
|
<li>
|
|
<p>Copyright 2008 Frank Mori Hess</p>
|
|
</li>
|
|
<li>
|
|
<p>Copyright 2012-2017 Glen Fernandes</p>
|
|
</li>
|
|
<li>
|
|
<p>Copyright 2013 Andrey Semashev</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>and is distributed under the <a href="http://www.boost.org/LICENSE_1_0.txt">Boost Software License, Version 1.0</a>.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="footer">
|
|
<div id="footer-text">
|
|
Last updated 2021-04-13 16:22:55 UTC
|
|
</div>
|
|
</div>
|
|
<style>
|
|
|
|
*:not(pre)>code { background: none; color: #600000; }
|
|
:not(pre):not([class^=L])>code { background: none; color: #600000; }
|
|
table tr.even, table tr.alt, table tr:nth-of-type(even) { background: none; }
|
|
|
|
</style>
|
|
</body>
|
|
</html> |