calling placement new for elements of a deque

H

hbdevelop1

Hello
For optimisation reasons, I am re-using not used objects in my deque for new objects.
I am doing that this way :
void Score::Add(const char *str, Coordinates &sp)
{
for(deque<Text>::iterator it=scores.begin();it!=scores.end(); ++it)
{
if(it->notUsed==1)
{
it->Reset(str,sp);
return;
}
}

scores.push_back(Text(str,sp));
}

I thought it would be more convenient to call the placement new on the notUsed object instead of Reset.
How can I do this ?
How can I get the address of the not used object so I can use it in the new placement operator?


Thank you in advance
 
V

Victor Bazarov

For optimisation reasons, I am re-using not used objects in my deque for new objects.
I am doing that this way :
void Score::Add(const char *str, Coordinates &sp)
{
for(deque<Text>::iterator it=scores.begin();it!=scores.end(); ++it)
{
if(it->notUsed==1)
{
it->Reset(str,sp);
return;
}
}

scores.push_back(Text(str,sp));
}

I thought it would be more convenient to call the placement new on the notUsed object instead of Reset.
How can I do this ?
How can I get the address of the not used object so I can use it in the new placement operator?

You can get a reference to the object through operator* of the iterator.
Then you can use the operator& to get the address of the object. Keep
in mind, however, that generally the constructor calls need to match the
destructor calls, so don't forget to destroy the object using a direct
call to the destructor before constructing a new one there. Something like

if (it->notUsed == 1)
{
Text *pUnused = &(*it);
pUnused->~Text(); // destroy
new (pUnused) Text(str, sp);
return;
}

Remember to include <memory> for placement new operator.

Not sure this is the best approach, though. Why do you think that using
Reset is inconvenient?

V
 
R

red floyd

if (it->notUsed == 1)
{
Text *pUnused = &(*it);
pUnused->~Text(); // destroy
new (pUnused) Text(str, sp);
return;
}

Remember to include <memory> for placement new operator.

Not sure this is the best approach, though. Why do you think that using
Reset is inconvenient?

The only reason I can see for using placement new instead of a reset is
that some const members may need updating for the new data. Otherwise
a reset should be fine.
 
H

hbdevelop1

The reason why I don't want to use Reset is because it holds the same code as the constructor and is only used in this case.
So I just wondered if I could get rid of Reset and use the constructor, for both, when pushing for the first time and when resetting.
And now, red floyd has given another reason why I might want to use the placement new in future.

Thank you very much Victor and red for your help and constructive feed back

hbdevelop1
 
R

red floyd

The reason why I don't want to use Reset is because it holds the same code as the constructor and is only used in this case.
So I just wondered if I could get rid of Reset and use the constructor, for both, when pushing for the first time and when resetting.
And now, red floyd has given another reason why I might want to use the placement new in future.

Thank you very much Victor and red for your help and constructive feed back

1. Please don't top-post.

2. I'd be VERRRRY careful about using placement new for that unless
you ABSOLUTELY POSITIVELY need to do so. I would definitely prefer
a Reset() function, or even an operator=(). Remember, readability
and maintainability trump cleverness every single time.

Also remember Hoare's law (also attributed to Knuth, or vice-versa):
"Premature optimization is the root of all evil."

Do you *really* need to do this "for efficency reasons"? Have you
actually benchmarked to see if your insertion/deletion code is a
bottleneck? Would an alternate data structure such as a std::list<>
perhaps suit your purposes better?

Think about that before embarking on this path.
 
H

hbdevelop1

1. Please don't top-post.



2. I'd be VERRRRY careful about using placement new for that unless

you ABSOLUTELY POSITIVELY need to do so. I would definitely prefer

a Reset() function, or even an operator=(). Remember, readability

and maintainability trump cleverness every single time.



Also remember Hoare's law (also attributed to Knuth, or vice-versa):

"Premature optimization is the root of all evil."



Do you *really* need to do this "for efficency reasons"? Have you

actually benchmarked to see if your insertion/deletion code is a

bottleneck? Would an alternate data structure such as a std::list<>

perhaps suit your purposes better?



Think about that before embarking on this path.

I used "optimization" for the wrong thing. In fact I wanted to mean writing less code, and not having two functions doing almost the same thing.

I do agree with you on going about optimizing code using figures and through profiling.
I liked your point on readability and maintainability and on thinking about other data structure.

Thank you for your advice on being pragmatic in optimization
 
Ö

Öö Tiib

Hello
For optimisation reasons, I am re-using not used objects in my deque for new objects.
I am doing that this way :
void Score::Add(const char *str, Coordinates &sp)
{
for(deque<Text>::iterator it=scores.begin();it!=scores.end(); ++it)
{
if(it->notUsed==1)
{
it->Reset(str,sp);
return;
}
}

scores.push_back(Text(str,sp));
}

I thought it would be more convenient to call the placement new on the notUsed object
instead of Reset.
How can I do this ?
How can I get the address of the not used object so I can use it in the new placement
operator?


Thank you in advance

Others have already answered about that placement new.

Regardless if you use it or not I wanted to comment that typically such
reuse is done with linked list of unused elements (not by for-cycling over
whole container). It is because if the container is small and rarely added
to / erased from then the whole reuse is likely not worth it ... but
otherwise cycling in it is also wasteful. Something like that:

void Score::Add( const char *str, Coordinates &sp )
{
Text* toReplace = firstUnused;
if ( toReplace == nullptr )
{
scores.emplace_back( str, sp );
}
else
{
firstUnused = ( toReplace->nextUnused == toReplace ) ? nullptr : toReplace->nextUnused;
toReplace->swap( Text( str, sp ) );
}
}

That involves that you build the linked list when elements become
unused.
 

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,969
Messages
2,570,161
Members
46,709
Latest member
AustinMudi

Latest Threads

Top