Freestore allocation etc

P

Philipp

Hello, in my main() I have code which looks like this

MyClass* myObject;
if ( param.isValid() )
myObject = new MyClass(otherParam, param);
else
myObject = new MyClass(otherParam);

-----
Now myObject is allocated as freestore which is not so good (says FAQ
31.4
http://www.parashift.com/c++-faq-lite/value-vs-ref-semantics.html#faq-31.7)

Is it possible to do the same thing by using value semantics?
Note that MyClass does not have a constructor without arguments.

Thanks Phil
 
M

Moonlit

Hi,

Maybe

MyClass MyObject( otherParam, param )

--


classs MyClass
T otherParam;
T1 param;
static const T1 OtherValue;
......
public:
MyClass( const T& otherParam, const T1& param ):
otherParam( otherParam ),
param( param.isValid() ? param : OtherValue )
{}


Regards, Ron AF Greve

http://moonlit.xs4all.nl
 
T

Thomas Tutone

Philipp said:
Hello, in my main() I have code which looks like this

MyClass* myObject;
if ( param.isValid() )
myObject = new MyClass(otherParam, param);
else
myObject = new MyClass(otherParam);

Depends upon the situation. But let's assume that using the free store
is bad in your particular situation.
Is it possible to do the same thing by using value semantics?
Note that MyClass does not have a constructor without arguments.

MyClass myObject =
param.isValid() ? MyClass(otherParam, param)
: MyClass(otherParam);

Whether or not this is efficient may depend on (1) how good your
compiler's optimizer is and (2) (if the optimizer isn't able to help
you here) whether or not copy construction is expensive.

Best regards,

Tom
 
R

Rolf Magnus

Thomas said:
http://www.parashift.com/c++-faq-lite/value-vs-ref-semantics.html#faq-31.7)

Depends upon the situation. But let's assume that using the free store
is bad in your particular situation.


MyClass myObject =
param.isValid() ? MyClass(otherParam, param)
: MyClass(otherParam);

Whether or not this is efficient may depend on (1) how good your
compiler's optimizer is and (2) (if the optimizer isn't able to help
you here) whether or not copy construction is expensive.

If you only need const access, you could also put the code that handles the
actual work into a separate function:

void do_stuff(MyClass& obj);

... in main:
if (param.isValid())
{
do_stuff(MyClass(otherParam, param);
}
else
{
do_stuff(MyClass(otherParam);
}

Or just put the validity check into the constructor of MyClass, so that you
can always pass param to it.
 
R

Rolf Magnus

Rolf said:
If you only need const access, you could also put the code that handles
the actual work into a separate function:

void do_stuff(MyClass& obj);

... in main:
if (param.isValid())
{
do_stuff(MyClass(otherParam, param);
}
else
{
do_stuff(MyClass(otherParam);
}

Rethinking it.. to allow non-const access, you could just do:

if (param.isValid())
{
MyClass obj(otherParam, param);
do_stuff(obj);
}
else
{
MyClass obj(otherParam);
do_stuff(obj);
}
 
P

Philipp

Thomas said:
Depends upon the situation. But let's assume that using the free store
is bad in your particular situation.

I want to make these changes to get faster code. Is it possible to give
some rule of thumb on where and when it is essential to change from free
store to static allocation (is this the right wording?)

Thanks Phil
 
P

Philipp

Rolf said:
Rolf Magnus wrote:




Rethinking it.. to allow non-const access, you could just do:

if (param.isValid())
{
MyClass obj(otherParam, param);
do_stuff(obj);
}
else
{
MyClass obj(otherParam);
do_stuff(obj);
}

Thanks for your answer.

The point is that the object must survive the "if" curly-brackets
because I want to use it later on. The "if" statement is just there to
construct it correctly (depending if param is OK or not).
 
P

Philipp

Hi,
>
> Maybe
>
> MyClass MyObject( otherParam, param )
>
> classs MyClass
> T otherParam;
> T1 param;
> static const T1 OtherValue;
> ..... public: MyClass( const T& otherParam, const T1& param ):
> otherParam( otherParam ), param( param.isValid() ?
> param : OtherValue ) {}

I get the idea, but in my case, if the param is not available it has to
be computed first, thats why there are two different ctors.

But I can call the code which computes the param instead of your value
"OtherValue".

Thanks Phil


PS: You may want to avoid using double dash -- in your posts, as this is
recognized as the separator for the signature and so prevents automatic
quoting of your message.
 
R

Rolf Magnus

Philipp said:
PS: You may want to avoid using double dash -- in your posts, as this is
recognized as the separator for the signature and so prevents automatic
quoting of your message.

Only if it's followed by a space character. But that just happens to be the
case here.
 
R

Rolf Magnus

Philipp said:
Thanks for your answer.

The point is that the object must survive the "if" curly-brackets
because I want to use it later on.

My point was that you put "later on" into do_stuff().
 
F

Frederick Gotham

Philipp posted:
MyClass* myObject;
if ( param.isValid() )
myObject = new MyClass(otherParam, param);
else
myObject = new MyClass(otherParam);


Maybe something like:

#include <new>
#include <iostream>
#include <cstdlib>

using std::cout;
using std::abort;

#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>

using boost::alignment_of;
using boost::aligned_storage;

class MyClass {
private:

int *const p;

MyClass(MyClass const &); /* Can't copy-construct! */

public:

MyClass(char const*) : p(new int)
{
cout << "Constructing!\n";
}

~MyClass()
{
delete p;
cout << "Destructing!\n";
}
};

int val = 3;

int main()
{
aligned_storage<sizeof(MyClass),
alignment_of<MyClass>::value>::type mem;

switch(val)
{
case 0: ::new(&mem) MyClass("a"); break;
case 1: ::new(&mem) MyClass("e"); break;
case 2: ::new(&mem) MyClass("i"); break;
case 3: ::new(&mem) MyClass("o"); break;
case 4: ::new(&mem) MyClass("u"); break;

default: abort();
}

MyClass &obj = reinterpret_cast<MyClass&>(mem);

/**********************

Do some stuff

**********************/

obj.~MyClass();
}
 
P

peter koch

Philipp said:
I want to make these changes to get faster code.

Okay. I assume you did profile the code and determine that "new" to be
a bottleneck? There is absolutely no reason to optimise early.
Is it possible to give
some rule of thumb on where and when it is essential to change from free
store to static allocation (is this the right wording?)

It is "automatic" allocation. Always prefer this (unless you have HUGE
objects). This will also be the fastest (assuming you have a halfway
decent compiler)

/Peter
 
O

Old Wolf

Thomas said:
MyClass myObject =
param.isValid() ? MyClass(otherParam, param)
: MyClass(otherParam);

A way that doesn't rely on the copy constructor, and
allows you to have creation blocks that are too
complicated for the ternary operator:

std::auto_ptr<MyClass> silly_ ;

if ( param.isValid() )
silly_ = new MyClass(otherParam, param);
else
silly_ = new MyClass(otherParam);

MyClass &myObject = *silly_.get();

// now just use myObject and not silly_
 
P

Philipp

peter said:
Okay. I assume you did profile the code and determine that "new" to be
a bottleneck? There is absolutely no reason to optimise early.

Yes I did profile and "new" is not a bottleneck in itself (0.8% of exec
time / 3,837,659,004 calls), but I have read that fetching memory from
the heap is slower than from the stack (?) and also that the heap needs
time to garbage collect... What do you think of this?

Phil
 
J

Jerry Coffin

[ ... ]
Yes I did profile and "new" is not a bottleneck in itself (0.8% of exec
time / 3,837,659,004 calls), but I have read that fetching memory from
the heap is slower than from the stack (?)

Depending on circumtances, it might be -- for example, since the data
near the top of the stack tends to be heavily used, chances are good
that it'll be in the cache, assuming you're using a processor that has
one. OTOH, there's no guarantee of anything like that -- it's at least
theoretically possible the stack could be slower.
and also that the heap needs
time to garbage collect... What do you think of this?

C++ doesn't normally include a garbage collector unless you've added one
yourself.
 
J

Jim Langston

Philipp said:
Hello, in my main() I have code which looks like this

MyClass* myObject;
if ( param.isValid() )
myObject = new MyClass(otherParam, param);
else
myObject = new MyClass(otherParam);

-----
Now myObject is allocated as freestore which is not so good (says FAQ 31.4
http://www.parashift.com/c++-faq-lite/value-vs-ref-semantics.html#faq-31.7)

Is it possible to do the same thing by using value semantics?
Note that MyClass does not have a constructor without arguments.

Thanks Phil

What do you do different if the 2nd parm is not there? The simplest way, I
would think, would just be to pass 0 as the second parm and test for that in
the constructor, presuming that a 2nd parm of 0 is not a meaningful value.
 
B

Bart

Jerry said:
[ ... ]
Yes I did profile and "new" is not a bottleneck in itself (0.8% of exec
time / 3,837,659,004 calls), but I have read that fetching memory from
the heap is slower than from the stack (?)

Depending on circumtances, it might be -- for example, since the data
near the top of the stack tends to be heavily used, chances are good
that it'll be in the cache, assuming you're using a processor that has
one. OTOH, there's no guarantee of anything like that -- it's at least
theoretically possible the stack could be slower.

If anything is a bottleneck chances are good that it will be heavily
used, and thus in cache. Therefore, it doesn't make a difference.

Regards,
Bart.
 
B

Bart

Philipp said:
peter koch wrote:

Yes I did profile and "new" is not a bottleneck in itself (0.8% of exec
time / 3,837,659,004 calls), but I have read that fetching memory from
the heap is slower than from the stack (?) and also that the heap needs
time to garbage collect... What do you think of this?

Don't optimize anything unless you have proof that it's going to make a
difference. Make a temporary fork of your source and then compare the
code before the optimization with the code after. It's like a lab
experiment with the source code as your subject.

Regards,
Bart.
 
P

Philipp

Jim said:
What do you do different if the 2nd parm is not there? The simplest way, I
would think, would just be to pass 0 as the second parm and test for that in
the constructor, presuming that a 2nd parm of 0 is not a meaningful value.

Yes that's exactly what I already decided to do :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top