home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 32,181 of 33,346   
   Dave Abrahams to All   
   Re: Initialization and trivial construct   
   23 Apr 12 09:18:10   
   
   From: dave@boostpro.com   
      
   on Sun Apr 22 2012, brangdon-AT-cix.compulink.co.uk (Dave Harris) wrote:   
      
   > { Article reformatted; please limit your lines to 70 charaters -mod }   
   >   
   > roberts.noah@gmail.com (nroberts) wrote (abridged):   
   >> Say you were given a coding policy that stated, "Only initialize   
   >> members with non-trivial constructors and destructors in your   
   >> constructor's initialization list."  Assuming they mean what they   
   >> are saying, and understand the difference between trivial and   
   >> non-trivial constructors, could there be a reasonable explanation   
   >> for this policy?   
   >   
   > They may be trying to say that:   
   >   
   >       Class::Class() : a(0), b(0), c(0), d(0) {   
   >       }   
   >   
   > would be better written as:   
   >   
   >       Class::Class() {   
   >           a = 0;   
   >           b = 0;   
   >           c = 0;   
   >           d = 0;   
   >       }   
   >   
   > The former may be more efficient if the members have code in their   
   > constructors, but if they are just ints, then the efficiency will be   
   > about the same. The latter version is arguably easier to read, write   
   > and edit.   
      
   I think Dave H. is being overly generous to the designers of such a   
   policy.  IMO the disadvantages of putting things in the constructor body   
   that could go in the initialization list outweigh the advantages by a   
   very significant margin.   
      
   As soon as you put something in the constructor body, you've introduced   
   mutation, which makes code much harder to reason about.  Objects   
   constructed in the initializer list don't exist until they're   
   initialized, so there is no mutation.  You've also introduced semantics   
   that can't be automatically reversed if there's an exception.   
      
   Like the use of "hungarian notation", the policy makes the details of   
   code sensitive to the specific types used, rather than to the concepts   
   they model---should I really have to rewrite constructors if I   
   replace   
      
         typedef double fraction;   
      
   with   
      
         typedef boost::rational fraction;   
      
   ?   
      
   These are just the first three things that pop to mind; I'm sure I could   
   go on.   
      
   > It matters more when the initialisation is more complex. For example,   
   > the latter version makes the order of evaluation apparent in the code;   
   > in the former version the order is determined by the class definition,   
   > which may be in a different source file.   
      
   And about which most compilers can warn you if you don't match up the   
   order.   
      
   > If you need some code to calculate the initial values, in the latter   
   > version you can just put it on the previous line, and add whatever   
   > intermediate variables or function calls you need. In the former   
   > version you have to write a separate function to return the initial   
   > value you want, and either pass lots of arguments to it, or else rely   
   > on the order of initialisation which as I've already noted is   
   > fraught. Let's not even think that we might need different exception   
   > handlers.   
      
   Yes, let's not!  Seriously, how often does that happen?   
      
   > Previous to C++11, there were things that couldn't be initialised by   
   > initialiser lists at all.   
   >   
   > Basically, assignment statements are simple. Everyone understands   
   > them.  Initialisation lists are weird   
      
   They're weird if you treat them that way, i.e. by not getting in the   
   habit of using them everywhere.   
      
   > and full of restrictions and special cases;   
      
   A list, please!  I've almost never felt limited by what I could do in   
   initialization lists... and, special cases?  Really?   
      
   > they are part of what makes C++ hard.   
      
   Au contraire, they are part of what make C++ easy, if you know how to   
   use them and think about them.  This is like saying "virtual functions   
   or exceptions are part of what make C++ hard."  If they look mysterious   
   to you, you'll tend to avoid them, they'll remain mysterious, and you'll   
   always be fighting the language.  If you embrace them and learn to   
   understand the abstractions they offer, they'll make everything easier.   
      
   > Sometimes you need them for performance, though.   
      
   Or, from my point of view: *very* occasionally you'll need to put code   
   in the constructor body, but the more you limit those occasions, the   
   easier your code will be to read, write, maintain, and understand.   
      
   --   
   Dave Abrahams   
   BoostPro Computing   
   http://www.boostpro.com   
      
      
         [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
         [ comp.lang.c++.moderated.    First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca