STL removal algorithm question | | |
Howdy
I have code similar to this in my project:
Note: BSTR is an abomination conjured up some disturbed person in the
COM world. BSTR strings must be allocated/deallocated using the
SysAllocString/SysFreeString Windows APIs.
typedef struct tagMyStruct
{
BSTR somestring;
BSTR someotherstring;
} MyStruct;
vector<MyStruct> my_struct;
over the course of my app, I allocate the BSTRs inside MyStruct and
stuff them into the vector.
When the time comes to get rid of them I was wondering if there is a
way to free the memory pointed to by the BSTR's in every MyStruct
instance inside the vector using a _single_ STL algorithm call?
Currently I use a combination of for_each (with a predicate to delete
the BSTRs) followed by a call to my_struct.erase(mystruct.begin(),
mystruct.end()).
There must be a better way to do this, right?
I looked up remove and remove_if, but they don't seem to be right for
my situation... | | | | re: STL removal algorithm question
Dilip wrote:[color=blue]
> I have code similar to this in my project:
>
> Note: BSTR is an abomination conjured up some disturbed person in the
> COM world. BSTR strings must be allocated/deallocated using the
> SysAllocString/SysFreeString Windows APIs.[/color]
Noted.
[color=blue]
> typedef struct tagMyStruct
> {
> BSTR somestring;
> BSTR someotherstring;
> } MyStruct;[/color]
Please use C++ way of defining types, it's so much easier:
struct MyStruct
{
BSTR somestring;
BSTR someotherstring;
};
[color=blue]
>
> vector<MyStruct> my_struct;
>
> over the course of my app, I allocate the BSTRs inside MyStruct and
> stuff them into the vector.[/color]
Do you allocate those BSTR yourself? Why not give it to MyStruct to
allocate? You know, like, in a constructor, for example...
[color=blue]
> When the time comes to get rid of them I was wondering if there is a
> way to free the memory pointed to by the BSTR's in every MyStruct
> instance inside the vector using a _single_ STL algorithm call?[/color]
Define the destructor in MyStruct. Make it deallocate those things.
Of course, to follow the Rule of Three, you will need to define the
copy c-tor and the assignment op as well.
After that, a simple destruction of the vector will free up all the
things.
[color=blue]
> Currently I use a combination of for_each (with a predicate to delete
> the BSTRs) followed by a call to my_struct.erase(mystruct.begin(),
> mystruct.end()).[/color]
OK
[color=blue]
> There must be a better way to do this, right?[/color]
There must be. Dynamic memory management needs to be the responsibility
of the owner of that memory. So, let MyStruct handle its own memory as
it should.
[color=blue]
> I looked up remove and remove_if, but they don't seem to be right for
> my situation...[/color]
They are not.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask | | | | re: STL removal algorithm question
"Dilip" <rdilipk@lycos.com> wrote in message
news:1146085245.308559.301400@t31g2000cwb.googlegr oups.com...[color=blue]
>
> Howdy
>
> I have code similar to this in my project:
>
> Note: BSTR is an abomination conjured up some disturbed person in the
> COM world. BSTR strings must be allocated/deallocated using the
> SysAllocString/SysFreeString Windows APIs.
>
> typedef struct tagMyStruct
> {
> BSTR somestring;
> BSTR someotherstring;
> } MyStruct;
>
> vector<MyStruct> my_struct;
>
> over the course of my app, I allocate the BSTRs inside MyStruct and
> stuff them into the vector.
>
> When the time comes to get rid of them I was wondering if there is a
> way to free the memory pointed to by the BSTR's in every MyStruct
> instance inside the vector using a _single_ STL algorithm call?
> Currently I use a combination of for_each (with a predicate to delete
> the BSTRs) followed by a call to my_struct.erase(mystruct.begin(),
> mystruct.end()).
>
> There must be a better way to do this, right?
>
> I looked up remove and remove_if, but they don't seem to be right for
> my situation...[/color]
struct MyStruct
{
BSTR somestring;
BSTR someotherstring;
MyStruct(/* params */)
{
// allocate
}
~MyStruct()
{
// de-allocate
}
};
-Mike | | | | re: STL removal algorithm question
Victor Bazarov wrote:[color=blue]
> Dilip wrote:
> Please use C++ way of defining types, it's so much easier:
>
> struct MyStruct
> {
> BSTR somestring;
> BSTR someotherstring;
> };[/color]
I would except for that damocle's sword called "company policy"
[color=blue][color=green]
> >
> > vector<MyStruct> my_struct;
> >
> > over the course of my app, I allocate the BSTRs inside MyStruct and
> > stuff them into the vector.[/color]
>
> Do you allocate those BSTR yourself? Why not give it to MyStruct to
> allocate? You know, like, in a constructor, for example...[/color]
See, the problem is I simplified this struct a little too much. This
struct gets used across COM boundaries so I have to put it in a IDL
file and once I do that I don't think I can start adding ctors/dtors
and other stuff.
[color=blue][color=green]
> > When the time comes to get rid of them I was wondering if there is a
> > way to free the memory pointed to by the BSTR's in every MyStruct
> > instance inside the vector using a _single_ STL algorithm call?[/color]
>
> Define the destructor in MyStruct. Make it deallocate those things.
> Of course, to follow the Rule of Three, you will need to define the
> copy c-tor and the assignment op as well.[/color]
Apologies for the silly question but I presume vector.erase will call
dtor of the contained objects? If not I may not be able to use this
because the vector undergoes erasure/insertion during the lifetime of
my application and during such erasure I want to be able to free up the
BSTRs memory allocated inside every instance of MyStruct. IOW I have
engineered a situation where the capacity of the vector remains intact
-- its just its size() that contracts & expands.
[color=blue][color=green]
> > I looked up remove and remove_if, but they don't seem to be right for
> > my situation...[/color]
>
> They are not.[/color]
Thanks for confirming. I read Items 33/34 of Scott Meyers ESTL just
now -- I won't even go near it! | | | | re: STL removal algorithm question
* Victor Bazarov:[color=blue]
> Dilip wrote:[color=green]
>> I have code similar to this in my project:
>>
>> Note: BSTR is an abomination conjured up some disturbed person in the
>> COM world. BSTR strings must be allocated/deallocated using the
>> SysAllocString/SysFreeString Windows APIs.[/color]
>
> Noted.
>[color=green]
>> typedef struct tagMyStruct
>> {
>> BSTR somestring;
>> BSTR someotherstring;
>> } MyStruct;[/color]
>
> Please use C++ way of defining types, it's so much easier:
>
> struct MyStruct
> {
> BSTR somestring;
> BSTR someotherstring;
> };
>[color=green]
>> vector<MyStruct> my_struct;
>>
>> over the course of my app, I allocate the BSTRs inside MyStruct and
>> stuff them into the vector.[/color]
>
> Do you allocate those BSTR yourself? Why not give it to MyStruct to
> allocate? You know, like, in a constructor, for example...
>[color=green]
>> When the time comes to get rid of them I was wondering if there is a
>> way to free the memory pointed to by the BSTR's in every MyStruct
>> instance inside the vector using a _single_ STL algorithm call?[/color]
>
> Define the destructor in MyStruct. Make it deallocate those things.
> Of course, to follow the Rule of Three, you will need to define the
> copy c-tor and the assignment op as well.[/color]
That will be hugely inefficient when a MyStruct is copied within the
vector, as happens e.g. when the vector reallocates.
One slightly less inefficient way could be to use boost::shared_ptr to
encapsulate a BSTR (the BSTR type is a pointer).
But, personally I'd encapsulate that vector in a class, because it's
evidently an implementation of something with a very restricted set of
operations, and use an ordinary for loop in the class' destructor.
--
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? | | | | re: STL removal algorithm question
Dilip wrote:[color=blue]
> [..]
> Apologies for the silly question but I presume vector.erase will call
> dtor of the contained objects?[/color]
That is correct. How does it help you? Your MyStruct has no d-tor,
and the one that the compiler creates for you won't deallocate your
BSTR members using whatever functions you need.
[color=blue]
> If not I may not be able to use this
> because the vector undergoes erasure/insertion during the lifetime of
> my application and during such erasure I want to be able to free up
> the BSTRs memory allocated inside every instance of MyStruct. IOW I
> have engineered a situation where the capacity of the vector remains
> intact -- its just its size() that contracts & expands.[/color]
The bottom line: if you have resource acquisition/dismissal during
exectuion of your program, you need to leave it to creation/destruction
of objects. RAII is one of the cornerstones of proper OOP.
As to COM implications, please ask in a Microsoft newsgroup. I am not
certain what you can or cannot do, and this is not the right place to
discsuss it.
V
--
Please remove capital As from my address when replying by mail | | | | re: STL removal algorithm question
Victor Bazarov wrote:[color=blue]
> Dilip wrote:[color=green]
> > [..]
> > Apologies for the silly question but I presume vector.erase will call
> > dtor of the contained objects?[/color]
>
> That is correct. How does it help you? Your MyStruct has no d-tor,
> and the one that the compiler creates for you won't deallocate your
> BSTR members using whatever functions you need.[/color]
I know what a compiler generated dtor can and cannot do unless I put in
my own code to deallocate/allocate whatever I want to. That was not my
question -- I was simply trying to confirm calling vector.erase does
indeed call the dtor of the contained objects.
[color=blue][color=green]
> > If not I may not be able to use this
> > because the vector undergoes erasure/insertion during the lifetime of
> > my application and during such erasure I want to be able to free up
> > the BSTRs memory allocated inside every instance of MyStruct. IOW I
> > have engineered a situation where the capacity of the vector remains
> > intact -- its just its size() that contracts & expands.[/color]
>
> The bottom line: if you have resource acquisition/dismissal during
> exectuion of your program, you need to leave it to creation/destruction
> of objects. RAII is one of the cornerstones of proper OOP.[/color]
I know that -- the reason why I posted this question in the first place
was because I couldn't follow proper OOP idiom here and hence was
looking for a clever way to use some STL algorithm I have never ran
into so far to delete memory allocated by the members of MyStruct _and_
erase the individual instances. IOW, I was looking for a better way
than the for_each/vector.erase combination.
[color=blue]
> As to COM implications, please ask in a Microsoft newsgroup. I am not
> certain what you can or cannot do, and this is not the right place to
> discsuss it.[/color]
I brought up COM only to explain what a BSTR was. My question was and
still remains a C++ question. | | | | re: STL removal algorithm question
Alf P. Steinbach wrote:[color=blue]
> That will be hugely inefficient when a MyStruct is copied within the
> vector, as happens e.g. when the vector reallocates.
>
> One slightly less inefficient way could be to use boost::shared_ptr to
> encapsulate a BSTR (the BSTR type is a pointer).
>
> But, personally I'd encapsulate that vector in a class, because it's
> evidently an implementation of something with a very restricted set of
> operations, and use an ordinary for loop in the class' destructor.[/color]
My only concern in starting this thread was to find out whether a
for_each and a vector.erase might turn out to be inefficient as the
calls completely traverse the vector 2 times.
As a side note, a vector re-allocation cannot happen in my system
because I have locked the capacity at a pre-determined limit and knock
off the elements once that limit is hit.
Unfortunately I can't use Boost :-( | | | | re: STL removal algorithm question
Dilip wrote:[color=blue]
> Victor Bazarov wrote:[color=green]
>>
>> struct MyStruct
>> {
>> BSTR somestring;
>> BSTR someotherstring;
>> };[color=darkred]
>>>
>>> vector<MyStruct> my_struct;
>>>[/color][/color]
>
> See, the problem is I simplified this struct a little too much. This
> struct gets used across COM boundaries so I have to put it in a IDL
> file and once I do that I don't think I can start adding ctors/dtors
> and other stuff.[/color]
You will save a lot of headaches by not using this struct
anywhere, except in COM interface calls. If you need to
manipulate this data yourself, define your own struct, eg:
struct ProperStruct { std::wstring some, someother; }
and include a functions to convert between a ProperStruct
and a MyStruct when it comes time to make an interface call.
I recommend this strategy for deleting strings: maintain a
separate container of all your BSTRs. When you've finished
with your vector, just destroy the vector normally. Then go
through the separate container and SysFreeString all of them. | | | | re: STL removal algorithm question
Old Wolf wrote:[color=blue]
> I recommend this strategy for deleting strings: maintain a
> separate container of all your BSTRs.[/color]
Let me add that this is only if you decide to stick with the
idea of using a vector of structs of BSTR. My preferred
solution is to work with structs of CComBSTR, or
some other string type; and then generate a struct of BSTR
only when it's needed for a COM interface call; it makes
all of this management crap unnecessary.
[color=blue]
> When you've finished
> with your vector, just destroy the vector normally. Then go
> through the separate container and SysFreeString all of them.[/color]
Something like this:
struct BstrManager
{
~BstrManager() { clear(); }
void clear()
{
for_each(all.begin(), all.end(), SysFreeString);
all.clear();
}
BSTR createString(wchar_t const *s, size_t len)
{
BSTR b = SysAllocStringLen(s, len);
all.push_back(b);
return b;
}
BSTR copyString( BSTR s )
{
BSTR b = SysAllocString(s);
all.push_back(b);
return b;
}
void deleteString( BSTR b )
{
std::vector<BSTR>::iterator it = all.find(b);
if ( it != all.end() ) { SysFreeString(b); all.erase(it); }
}
private:
std::vector<BSTR> all;
};
Then in your code you can go:
MyStruct m;
m.somestring = manager.createString(L"Hello", 5);
m.otherstring = manager.copyString(m.somestring);
vec.push_back(m);
// ......
vec.clear();
manager.clear(); | | | | re: STL removal algorithm question
Dilip wrote:
[color=blue]
> My only concern in starting this thread was to find out whether a
> for_each and a vector.erase might turn out to be inefficient as the
> calls completely traverse the vector 2 times.[/color]
Alternating between deleting a single BSTR and erasing a single element
from a vector is also inefficient. And if you erase an entire iterator
range, it's likely to be more efficient than looping yourself (cause
the
compiler can see it has to update size() only once, etc. )
HTH,
Michiel Salters | | | | re: STL removal algorithm question
* Michiel.Salters@tomtom.com:[color=blue]
> Dilip wrote:
>[color=green]
>> My only concern in starting this thread was to find out whether a
>> for_each and a vector.erase might turn out to be inefficient as the
>> calls completely traverse the vector 2 times.[/color]
>
> Alternating between deleting a single BSTR and erasing a single element
> from a vector is also inefficient. And if you erase an entire iterator
> range, it's likely to be more efficient than looping yourself (cause
> the
> compiler can see it has to update size() only once, etc. )[/color]
Uh, well. It's potentially an O(n) operation as opposed to an O(n^2)
operation; the size() update is mostly irrelevant, I should think.
However, for this concrete case the most efficient is to never erase.
--
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? |  | | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,471 network members.
|