{"id":104719,"date":"2021-01-15T07:00:00","date_gmt":"2021-01-15T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=104719"},"modified":"2021-01-15T06:46:44","modified_gmt":"2021-01-15T14:46:44","slug":"20210115-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20210115-00\/?p=104719","title":{"rendered":"The perils of the accidental C++ conversion constructor"},"content":{"rendered":"<p>Consider this class:<\/p>\n<pre>class Buffer\r\n{\r\npublic:\r\n  Buffer(size_t capacity);\r\n  Buffer(std::initializer_list&lt;int&gt; values);\r\n};\r\n<\/pre>\n<p>You can create an uninitialized buffer with a particular capacity, or you can create an initialized buffer.<\/p>\n<p>The one-parameter constructor also serves as a conversion constructor, resulting in the following:<\/p>\n<pre>Buffer buffer(24); \/\/ create a buffer of size 24\r\nBuffer buffer({ 1, 3, 5 }); \/\/ create an initialized 3-byte buffer\r\n<\/pre>\n<p>Okay, those don&#8217;t look too bad. But you also get this:<\/p>\n<pre>Buffer buffer = 24; \/\/ um...\r\nBuffer buffer = { 1, 3, 5 };\r\n<\/pre>\n<p>These are equivalent to the first two versions, but you have to admit that the <code>= 24<\/code> version looks really weird.<\/p>\n<p>You also get this:<\/p>\n<pre>extern void Send(Buffer const&amp; b);\r\nSend('c'); \/\/ um...\r\n<\/pre>\n<p>This totally compiles, but it doesn&#8217;t send the character <code>'c'<\/code>, which is what it looks like. Instead, it creates an uninitialized buffer of size <code>0x63 = 99<\/code> and sends it.<\/p>\n<p>If this is not what you intended, then you would be well-served to use the <code>explicit<\/code> keyword to prevent a constructor from being used as conversion constructions.<\/p>\n<pre>class Buffer\r\n{\r\npublic:\r\n  <span style=\"color: blue;\">explicit<\/span> Buffer(size_t capacity);\r\n  Buffer(std::initializer_list&lt;int&gt; values);\r\n};\r\n<\/pre>\n<p>I made the first constructor explicit, since I don&#8217;t want you to pass an integer where a buffer is expected. However, I left the initializer list as a valid conversion constructor because it seems reasonable to let someone write<\/p>\n<pre>Send({ 1, 2, 3 });\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Single-parameter constructors are also conversions.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-104719","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Single-parameter constructors are also conversions.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/104719","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=104719"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/104719\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=104719"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=104719"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=104719"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}