Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > constructor and reset method

Reply
Thread Tools

constructor and reset method

 
 
Christopher
Guest
Posts: n/a
 
      02-26-2008
Embarrassed to ask, but is there any functional difference between

class A
{
int m_x;
int m_y;

public:
A()
:
m_x(0),
m_y(0)
{
}

~A(){}

Reset()
{
m_x = 0;
m_y = 0;
}
};


class B
{
int m_x;
int m_y;

public:
B()
:
m_x(0),
m_y(0)
{
}

~B(){}

Reset()
{
B();
}
};


Both seem to compile and work as expected, but as I've learned over
the years, just because it runs and shows you what you want to see,
doesn't mean it works.

 
Reply With Quote
 
 
 
 
Jeff Schwab
Guest
Posts: n/a
 
      02-26-2008
Christopher wrote:
> Embarrassed to ask, but is there any functional difference between


[code like:]

class A {
int m_x;
int m_y;

public:
A() : m_x(0), m_y(0) { }

void Reset() {
m_x = 0;
m_y = 0;
}
};

class B {
int m_x;
int m_y;

public:
B(): m_x(0), m_y(0) { }

void Reset() { B(); }
};

> Both seem to compile and work as expected, but as I've learned over
> the years, just because it runs and shows you what you want to see,
> doesn't mean it works.


Smart man.

The method B::reset is not invoking the constructor on the right object.
It is only creating a temporary object of type B, and in no way
affecting the object on which Reset was called.

Your A::Reset approach is generally the right way to do this.
 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      02-26-2008
* Christopher:
> Embarrassed to ask, but is there any functional difference between
>
> class A
> {
> int m_x;
> int m_y;
>
> public:
> A()
> :
> m_x(0),
> m_y(0)
> {
> }
>
> ~A(){}
>
> Reset()
> {
> m_x = 0;
> m_y = 0;
> }
> };
>
>
> class B
> {
> int m_x;
> int m_y;
>
> public:
> B()
> :
> m_x(0),
> m_y(0)
> {
> }
>
> ~B(){}
>
> Reset()
> {
> B();
> }
> };
>
>
> Both seem to compile and work as expected, but as I've learned over
> the years, just because it runs and shows you what you want to see,
> doesn't mean it works.


B::Reset doesn't do anything.

What you have is a construction of a temporary.

That isn't a bad idea in and of itself (although it's probably not
what you intended), but it needs a little more support machinery:

class B
{
int myX;
int myY;
public:
B(): myX(0), myY(0) {}

reset() { *this = B(); }
};

Cheers, & hth.,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      02-26-2008
* Alf P. Steinbach:
> * Christopher:
>> Embarrassed to ask, but is there any functional difference between
>>
>> class A
>> {
>> int m_x;
>> int m_y;
>>
>> public:
>> A()
>> :
>> m_x(0),
>> m_y(0)
>> {
>> }
>>
>> ~A(){}
>>
>> Reset()
>> {
>> m_x = 0;
>> m_y = 0;
>> }
>> };
>>
>>
>> class B
>> {
>> int m_x;
>> int m_y;
>>
>> public:
>> B()
>> :
>> m_x(0),
>> m_y(0)
>> {
>> }
>>
>> ~B(){}
>>
>> Reset()
>> {
>> B();
>> }
>> };
>>
>>
>> Both seem to compile and work as expected, but as I've learned over
>> the years, just because it runs and shows you what you want to see,
>> doesn't mean it works.

>
> B::Reset doesn't do anything.
>
> What you have is a construction of a temporary.
>
> That isn't a bad idea in and of itself (although it's probably not
> what you intended), but it needs a little more support machinery:
>
> class B
> {
> int myX;
> int myY;
> public:
> B(): myX(0), myY(0) {}
>
> reset() { *this = B(); }
> };


Hm. Add a void.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
Jeff Schwab
Guest
Posts: n/a
 
      02-27-2008
Alf P. Steinbach wrote:
> * Christopher:


> reset() { *this = B(); }


I've never seen that before, but it does seem like a neat idea.

It seems like it would be (generally speaking) twice as slow as manual
member-by-member initialization, because of (a) the temporary object's
constructor, plus (b) the assignment operator.
 
Reply With Quote
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      02-27-2008
"Alf P. Steinbach" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> class B
> {
> int myX;
> int myY;
> public:
> B(): myX(0), myY(0) {}
>
> reset() { *this = B(); }
> };


Sometimes I go the other way around, as long as B is simple enough
that you can call Reset() on an unitialized B:

class B
{
int myX;
int myY;
public:
B() { Reset(); }
void Reset () {
myX = 0;
myY = 0;
}
};

But if you have to deallocate memory or something you still need to
initialize some things in the constructor:

class B
{
int *myInts;
public:
B() : myInts(NULL) { Reset(); }
void Reset() { // or something to this effect...
delete[] myInts;
myInts = NULL;
}
};

....and that all breaks down and turns pretty useless anyway once B
starts having members that are other complex objects (that you'd also
want to "Reset").

Jason

 
Reply With Quote
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      02-27-2008
On Feb 26, 11:12 pm, Jeff Schwab <(E-Mail Removed)> wrote:
> Alf P. Steinbach wrote:
> > * Christopher:
> > reset() { *this = B(); }

>
> I've never seen that before, but it does seem like a neat idea.
>
> It seems like it would be (generally speaking) twice as slow as manual
> member-by-member initialization, because of (a) the temporary object's
> constructor, plus (b) the assignment operator.


Just now I managed to get this working using placement new. Is there
anything bad that can happen with the following code (assuming the
constructor does not throw any exceptions):

class B {
public:
B () { }
~B () { }

void Reset () {
this->~B();
new (this) B();
}

};

I've done a good amount of testing on that just now and it seems to
work fine (even when B has other complex object members, etc.).
Assuming it's safe, it doesn't require you to implement an assignment
operator for complex B's, and doesn't create any temporaries. It seems
like it's just a different way of expressing the following, with the
addition of automatically calling member object destructors and
constructors:

class B {
public:
B () { Init(); }
~B () { Cleanup(); }
void Reset () {
Cleanup();
Init();
}
private:
// these do things:
void Init () { ... }
void Cleanup () { ... }
};

Jason
 
Reply With Quote
 
Jeff Schwab
Guest
Posts: n/a
 
      02-27-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> On Feb 26, 11:12 pm, Jeff Schwab <(E-Mail Removed)> wrote:
>> Alf P. Steinbach wrote:
>>> * Christopher:
>>> reset() { *this = B(); }

>> I've never seen that before, but it does seem like a neat idea.
>>
>> It seems like it would be (generally speaking) twice as slow as manual
>> member-by-member initialization, because of (a) the temporary object's
>> constructor, plus (b) the assignment operator.

>
> Just now I managed to get this working using placement new. Is there
> anything bad that can happen with the following code (assuming the
> constructor does not throw any exceptions):
>
> class B {
> public:
> B () { }
> ~B () { }
>
> void Reset () {
> this->~B();
> new (this) B();
> }
>
> };
>
> I've done a good amount of testing on that just now and it seems to
> work fine (even when B has other complex object members, etc.).
> Assuming it's safe, it doesn't require you to implement an assignment
> operator for complex B's, and doesn't create any temporaries. It seems
> like it's just a different way of expressing the following, with the
> addition of automatically calling member object destructors and
> constructors:
>
> class B {
> public:
> B () { Init(); }
> ~B () { Cleanup(); }
> void Reset () {
> Cleanup();
> Init();
> }
> private:
> // these do things:
> void Init () { ... }
> void Cleanup () { ... }
> };


The primary thing I would be concerned about is overwriting any
subobjects of B. If B has non-POD members, they may not take kindly to
be reconstructed in place, without any chance to delete resources they
were already holding.

For example: If B has a std::vector<int> member, the vector likely has
a pointer to some dynamically allocated memory. By using placement new,
rather than emptying the vector through its intended interface, you may
be overwriting the vector's pointer to its dynamically allocated memory,
such that the memory is leaked.
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      02-27-2008
* (E-Mail Removed):
> On Feb 26, 11:12 pm, Jeff Schwab <(E-Mail Removed)> wrote:
>> Alf P. Steinbach wrote:
>>> * Christopher:
>>> reset() { *this = B(); }

>> I've never seen that before, but it does seem like a neat idea.
>>
>> It seems like it would be (generally speaking) twice as slow as manual
>> member-by-member initialization, because of (a) the temporary object's
>> constructor, plus (b) the assignment operator.


No. Thinking about that would be premature optimization. Actually a 'reset'
member function indicates of itself premature optimization, the idea of reusing
an object to avoid some imagined micro-inefficiency, thereby complicating the
design.

For optimization, always first measure.


> Just now I managed to get this working using placement new. Is there
> anything bad that can happen with the following code (assuming the
> constructor does not throw any exceptions):
>
> class B {
> public:
> B () { }
> ~B () { }
>
> void Reset () {
> this->~B();
> new (this) B();
> }
>
> };
>
> I've done a good amount of testing on that just now and it seems to
> work fine (even when B has other complex object members, etc.).
> Assuming it's safe,


It isn't safe, in general.

In particular it's problematic if anyone ever derives from B: then you're
constructing the wrong kind of object.

To reuse the constructor logic e.g. in assignment operator, instead add a swap()
member function.


> it doesn't require you to implement an assignment
> operator for complex B's,


Assignment operator or not has nothing to with the above issue.


> and doesn't create any temporaries.


Temporaries are not inefficient. They're not ungood. You should not focus on
avoiding temporaries.


Cheers, & hth.,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
Triple-DES
Guest
Posts: n/a
 
      02-27-2008
On 27 Feb, 06:22, "(E-Mail Removed)"
<(E-Mail Removed)> wrote:
> On Feb 26, 11:12 pm, Jeff Schwab <(E-Mail Removed)> wrote:
>
> > Alf P. Steinbach wrote:
> > > * Christopher:
> > > * * * reset() { *this = B(); }

>
> > I've never seen that before, but it does seem like a neat idea.

>
> > It seems like it would be (generally speaking) twice as slow as manual
> > member-by-member initialization, because of (a) the temporary object's
> > constructor, plus (b) the assignment operator.

>
> Just now I managed to get this working using placement new. Is there
> anything bad that can happen with the following code (assuming the
> constructor does not throw any exceptions):
>
> class B {
> public:
> * B () { }
> * ~B () { }
>
> * void Reset () {
> * * this->~B();
> * * new (this) B();
> * }
>
> };
>
> I've done a good amount of testing on that just now and it seems to
> work fine (even when B has other complex object members, etc.).
> Assuming it's safe, it doesn't require you to implement an assignment
> operator for complex B's, and doesn't create any temporaries. It seems
> like it's just a different way of expressing the following, with the
> addition of automatically calling member object destructors and
> constructors:
>
> class B {
> public:
> * B () { Init(); }
> * ~B () { Cleanup(); }
> * void Reset () {
> * * Cleanup();
> * * Init();
> * }
> private:
> * // these do things:
> * void Init () { ... }
> * void Cleanup () { ... }
>
> };
>
> Jason


class B
{
public:
void Reset()
{
this->~B();
new (this) B();
}
virtual ~B() {}
};

class D : public B
{
// ...
};

int main()
{
B * b = new D; // Ok, *b is of type D
b->Reset(); // Oops, *b is of type B
}

DP
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
You will not be able to reset the access - can't reset. jc MCAD 0 12-09-2007 08:58 PM
A constructor calling another constructor (default constructor)? Generic Usenet Account C++ 10 11-28-2007 04:12 AM
CISCO 7XX / 761 password reset or reset to factory defaults Philipp Flesch Cisco 3 06-18-2006 07:47 PM
Confused by the constructor and cop-constructor. Xiangliang Meng C++ 9 06-25-2004 03:44 PM
why it's not possible calling constructor from constructor? Giulio C++ 9 06-25-2003 03:56 PM



Advertisments