{"id":99,"date":"2012-05-06T23:00:32","date_gmt":"2012-05-06T15:00:32","guid":{"rendered":"http:\/\/fishinbox.tk\/?p=99"},"modified":"2012-05-06T23:00:32","modified_gmt":"2012-05-06T15:00:32","slug":"effective-item-12-prefer-initialization-assignment-constructors","status":"publish","type":"post","link":"https:\/\/zhuangzr.me\/wordpress\/2012\/05\/effective-item-12-prefer-initialization-assignment-constructors\/","title":{"rendered":"Effective C++ Item 12: Prefer initialization to assignment in constructors"},"content":{"rendered":"<p>When you write the NamedPtr constructor, you have to transfer the values of the parameters to the corresponding<br \/>\ndata members. There are two ways to do this. The first is to use the member initialization list:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\ntemplate&lt;class T&gt;\nNamedPtr&lt;t&gt;::NamedPtr(const string&amp; initName, T *initPtr )\n: name(initName), ptr(initPtr)\n{}\n<\/pre>\n<p>The second is to make assignments in the constructor body:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\ntemplate&lt;class T&gt;\nNamedPtr&lt;t&gt;::NamedPtr(const string&amp; initName, T *initPtr)\n{\n    name = initName;\n    ptr = initPtr;\n}\n<\/pre>\n<p>There are important differences between these two approaches.<br \/>\nFrom a purely pragmatic point of view, there are times when the initialization list must be used. In particular,<br \/>\nconst and reference members may only be initialized, never assigned. So, if you decided that a NamedPtr<t><br \/>\nobject could never change its name or its pointer, you might follow the advice of Item 21 and declare the<br \/>\nmembers const:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\ntemplate&lt;class T&gt;\nclass NamedPtr {\npublic:\n    NamedPtr(const string&amp; initName, T *initPtr);\n...\nprivate:\n    const string name;\n    T * const ptr;\n};\n<\/pre>\n<p>This class definition requires that you use a member initialization list, because const members may only be<br \/>\ninitialized, never assigned.<br \/>\nYou&#8217;d obtain very different behavior if you decided that a NamedPtr<t> object should contain a reference to an<br \/>\nexisting name. Even so, you&#8217;d still have to initialize the reference on your constructors&#8217; member initialization<br \/>\nlists. Of course, you could also combine the two, yielding NamedPtr<t> objects with read-only access to names<br \/>\nthat might be modified outside the class:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\ntemplate&lt;class T&gt;\nclass NamedPtr {\npublic:\n    NamedPtr(const string&amp; initName, T *initPtr);\n...\nprivate:\n    const string&amp; name; \/\/ must be initialized via\n    \/\/ initializer list\n    T * const ptr; \/\/ must be initialized via\n    \/\/ initializer list\n};\n<\/pre>\n<p>The original class template, however, contains no const or reference members. Even so, using a member<br \/>\ninitialization list is still preferable to performing assignments inside the constructor. This time the reason is<br \/>\nefficiency. When a member initialization list is used, only a single string member function is called. When<br \/>\nassignment inside the constructor is used, two are called. To understand why, consider what happens when you<br \/>\ndeclare a NamedPtr<t> object.<br \/>\nConstruction of objects proceeds in two phases:<br \/>\n1. Initialization of data members. (See also Item 13.)<br \/>\n2. Execution of the body of the constructor that was called.<br \/>\n(For objects with base classes, base class member initialization and constructor body execution occurs prior to<br \/>\nthat for derived classes.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When you write the NamedPtr constructor, you have to transfer the values of the parameters to the corresponding data members. There are two ways to do this. The first is to use the member initialization list: template&lt;class T&gt; NamedPtr&lt;t&gt;::NamedPtr(const string&amp; initName, T *initPtr ) : name(initName), ptr(initPtr) {} The second is to make assignments in &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/zhuangzr.me\/wordpress\/2012\/05\/effective-item-12-prefer-initialization-assignment-constructors\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Effective C++ Item 12: Prefer initialization to assignment in constructors&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17],"tags":[25,27,30,35],"class_list":["post-99","post","type-post","status-publish","format-standard","hentry","category-cpp-programming","tag-c","tag-constructor","tag-effective-c","tag-initialization"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/zhuangzr.me\/wordpress\/wp-json\/wp\/v2\/posts\/99","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zhuangzr.me\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zhuangzr.me\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zhuangzr.me\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zhuangzr.me\/wordpress\/wp-json\/wp\/v2\/comments?post=99"}],"version-history":[{"count":0,"href":"https:\/\/zhuangzr.me\/wordpress\/wp-json\/wp\/v2\/posts\/99\/revisions"}],"wp:attachment":[{"href":"https:\/\/zhuangzr.me\/wordpress\/wp-json\/wp\/v2\/media?parent=99"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zhuangzr.me\/wordpress\/wp-json\/wp\/v2\/categories?post=99"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zhuangzr.me\/wordpress\/wp-json\/wp\/v2\/tags?post=99"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}