Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!rutgers!tut.cis.ohio-state.edu!ucbvax!ulysses!hector!jss From: jss@hector.UUCP (Jerry Schwarz) Newsgroups: comp.lang.c++ Subject: Re: Having constructors is expensive. Message-ID: <11615@ulysses.homer.nj.att.com> Date: 31 May 89 15:16:20 GMT References: Sender: netnews@ulysses.homer.nj.att.com Reply-To: jss@hector.UUCP (Jerry Schwarz) Distribution: comp Organization: AT&T Bell Laboratories Lines: 72 In article jeffb@grace.cs.washington.edu (Jeff Bowden) writes: > > The problem (which I found by examining the output of CC -F) is that >the empty constructor (which is defined in the class declaration, so it is >should to be inline) somehow gets incarnated and called as a normal function! > > This wouldn't be so bad except that I declare many arrays of vectors >of this class and I generally use only 10% of the elements. (I have an empty >constructor because of the vectors; fascist cfront doesn't like it when you >declare vectors of things which haven't any no-argument constructor). The reason C++ demands a no argument constructor is so that it can maintain what I call the "allocation guarantee". Namely every area of storage that it will call an X must be initialized by a constructor. In the case of something like X array[1000] this means that the X() constructor must be called 1000 times to "initialize" the areas that are holding an X. This is done by a function that is passed the constructor as an argument. This is why The X() constructor is being incarnated, and presumably it is also account for the profiling showing many calls to X(). > My current solution consists eliminating the constructors for this >class and using some overloaded `friend' functions in place of the constructors >(e.g. class foo { /*...*/ friend foo mkfoo(); /*...*/ }; ). This leads to a >vast improvement in performance, but it's damn ugly. Anyone have a better >suggestion/fix????? An alternative is to cause the allocation guarantee to be violated by a cast. Instead of allocating arrays directly create a class class arrayofX { public: arrayofX(int i) { a = (X*)new char[sizeof(X)*i] ; // by allocating as an array of char's // and then casting we avoid calls to // the X() constructor. } ~arrayofX() { delete a ; } X& operator[](int x) { return a[x] ; } private: X* a ; } ; This class can be used as follows arrayofX v(100) ; // v now behaves as if it had been declared // X v[100] ; X x ; v[5] = x ; // legal C++ is not "fascist". It does your require you to be explicit when you want to violate the typing of the language, but it allows you to do so. It does tend to require you to be more knowledgeable when you violate the typing than when you conform to the type system. IHHO this is a very reasonable attitude. Note that the above class will not work properly if X has virtual member functions. If you don't understand why, then you probably not use this technique. Jerry Schwarz AT&T Bell Labs, Murray Hill