Connecting Tech Pros Worldwide Forums | Help | Site Map

How to add and call a do-nothing non-default constructor?

Ng Hun Yang
Guest
 
Posts: n/a
#1: Oct 10 '05
I have a class that has a default constructor that initializes the
class's variables. Now I want to add a new constructor to skip the
initialization.

My attempt:
class Integer {
public:
class NoInit { }; // newly added

public:
Integer(): v_(0) { }
Integer(int v): v_(v) { }
Integer(NoInit) { } // newly added

private:
int v_;
};

Here's how it's used:
class SomeClass {
public:
SomeClass() { }

private:
Integer a_;
};

I want SomeClass's constructor to skip initializing a_, so I changed it
to:
SomeClass(): a_(Integer(Integer::NoInit())) { }

Shouldn't the compiler do RVO, find that it's an empty object and
optimize the initialization away?

But I found that the compiler insisted on copying from the
uninitialized temporary variable to a_.

I read about using dummy classes/enum/types as constructor parameters
to distinguish between constructors, but I can't recall where I read
it.

What did I do wrong and what should I change to achieve my goal?

I can't change Integer's default constructor, because there is code
that depends on the value being initialized. However, SomeClass is
special because it never uses the default value.

Here's how SomeClass looks like:
class SomeClass {
public:
SomeClass() { }

public:
void Start(const Integer &a) { a_ = a; fn1(); fn2(); fn3(); }

private:
void fn1(); // does something with a_
void fn2(); // does something with a_
void fn3(); // does something with a_

private:
Integer a_;
};

Why not change SomeClass to:
class SomeClass {
public:
SomeClass(const Integer &a): a_(a) { }

public:
void Start() { fn1(); fn2(); fn3(); }
};

Well, that's not the question I'm asking, isn't it? :-D


btw, I'm using the Green Hill's C++ MIPS compiler; optimization is
turned on. The Multi suite is version 4.something, but I don't know the
actual compiler version.


Victor Bazarov
Guest
 
Posts: n/a
#2: Oct 10 '05

re: How to add and call a do-nothing non-default constructor?


Ng Hun Yang wrote:[color=blue]
> I have a class that has a default constructor that initializes the
> class's variables. Now I want to add a new constructor to skip the
> initialization.
>
> My attempt:
> class Integer {
> public:
> class NoInit { }; // newly added
>
> public:
> Integer(): v_(0) { }
> Integer(int v): v_(v) { }
> Integer(NoInit) { } // newly added
>
> private:
> int v_;
> };
>
> Here's how it's used:
> class SomeClass {
> public:
> SomeClass() { }
>
> private:
> Integer a_;
> };
>
> I want SomeClass's constructor to skip initializing a_, so I changed it
> to:
> SomeClass(): a_(Integer(Integer::NoInit())) { }[/color]

Why the unnecessary intermediary? Couldn't you just write

SomeClass() : a_(Integer::NoInit()) {}

?
[color=blue]
> Shouldn't the compiler do RVO, find that it's an empty object and
> optimize the initialization away?[/color]

No, it should just use a particular constructor, which will leave the
'v_' data member uninitialised.
[color=blue]
> But I found that the compiler insisted on copying from the
> uninitialized temporary variable to a_.[/color]

Yes, you wrote it that way.
[color=blue]
> I read about using dummy classes/enum/types as constructor parameters
> to distinguish between constructors, but I can't recall where I read
> it.
>
> What did I do wrong and what should I change to achieve my goal?[/color]

Remove the extra temporary from the initialisation.
[color=blue]
> [...][/color]

V
Ng Hun Yang
Guest
 
Posts: n/a
#3: Oct 11 '05

re: How to add and call a do-nothing non-default constructor?


Victor Bazarov wrote:[color=blue][color=green]
> > I want SomeClass's constructor to skip initializing a_, so I changed it
> > to:
> > SomeClass(): a_(Integer(Integer::NoInit())) { }[/color][/color]
[color=blue]
> Why the unnecessary intermediary? Couldn't you just write
> SomeClass() : a_(Integer::NoInit()) {}
> ?[/color]

hmm, you're right! I forget a_(...) itself is a constructor call!

SomeClass() : a_(Integer::NoInit()) {}

works!

(Looks like I have to remove C++ from my resume. ;-))

But suppose now I convert this to the named constructor idiom:
class Integer {
private:
enum NoInitT { NoInitV };
explicit Integer(NoInitT) { }

public:
Integer(): v_(0) { }
Integer(int v): v_(v) { }
static Integer NoInit() { return Integer(NoInitV); }

private:
int v_;
};

class SomeClass {
public:
SomeClass(): a_(Integer::NoInit()) { }

private:
Integer a_;
};

Still the same thing, right?

However, NoInit() creates a temporary (uninitialized) return object
which is then copied to a_. Can't the compiler initialize a_ in-place?

Victor Bazarov
Guest
 
Posts: n/a
#4: Oct 11 '05

re: How to add and call a do-nothing non-default constructor?


Ng Hun Yang wrote:[color=blue]
> Victor Bazarov wrote:
>[color=green][color=darkred]
>>>I want SomeClass's constructor to skip initializing a_, so I changed it
>>>to:
>>> SomeClass(): a_(Integer(Integer::NoInit())) { }[/color][/color]
>
>[color=green]
>>Why the unnecessary intermediary? Couldn't you just write
>> SomeClass() : a_(Integer::NoInit()) {}
>>?[/color]
>
>
> hmm, you're right! I forget a_(...) itself is a constructor call!
>
> SomeClass() : a_(Integer::NoInit()) {}
>
> works!
>
> (Looks like I have to remove C++ from my resume. ;-))[/color]

If folks did that every time they use an extra copy, we'd probably have
less than a hundred of people with C++ on their resumes. :-)
[color=blue]
> But suppose now I convert this to the named constructor idiom:
> class Integer {
> private:
> enum NoInitT { NoInitV };
> explicit Integer(NoInitT) { }
>
> public:
> Integer(): v_(0) { }
> Integer(int v): v_(v) { }
> static Integer NoInit() { return Integer(NoInitV); }
>
> private:
> int v_;
> };
>
> class SomeClass {
> public:
> SomeClass(): a_(Integer::NoInit()) { }
>
> private:
> Integer a_;
> };
>
> Still the same thing, right?
>
> However, NoInit() creates a temporary (uninitialized) return object
> which is then copied to a_. Can't the compiler initialize a_ in-place?
>[/color]

I might be able to, or it might not. There is no requirement in the
Standard that the compiler does so. The Standard allows, however, to
omit the copying and initialise an object directly, even if the copy
constructor has side effects. So, set your optimization levels high
and hope for the best :-)

V
Closed Thread