Re: vectors and user-defined objects
In article <32bbeb00-f6a6-4b9d-9c04-a1671ace8b5d@i12g2000prf.googlegroups.com>,
James Kanze <james.kanze@gmail.com> wrote:
>On Jan 14, 6:19 pm, ytrem...@nyx.nyx.net (Yannick Tremblay) wrote:
>> In article
>> <ea77bb89-125d-4d44-b447-de6cae4a6...@j78g2000hsd.googlegroups.com>,
>
>> Jim <j...@astro.livjm.ac.uk> wrote:
>> >On Jan 14, 1:56 pm, jkherci...@gmx.net wrote:
>> >> Jim wrote:
>
>> >> > Just wondering which is better
>
>> >> > vector<record *> r;
>> >> > r.push_back(new record(x,y));
>
>> Although Kai-uwe talks about it in his point (b), I think this
>> needs to be highlighted as this is fundamentally wrong: the
>> above is a memory leak.
>
>It depends.
>
>In most cases where I've seen this, r would either have static
>lifetime or be a singleton, never destructed. The constructor
>of record would insert it into r, and the destructor removes it.
>It's actually a very, very common idiom for entity objects.
Note that the op code was:
r.push_back(new record(x,y));
That's very different from what you are suggesting above with a static
vector and record inserting themselves in it for reference.
>> The above code should never exist in isolation of its deleting
>> loop. If attempting to compare the two approaches, you must
>> include the deleting loop in the comparaison.
>
>> STL containers have value semantic and may copy their own
>> content freely around. STL containers do not know if they are
>> holding pointers or object and will never call "delete" on
>> their content.
>
>And? That's usually exactly what is wanted. If the container
>owns the objects, you'd usually use values (and the objects
>cannot have identity, because the container copies them). If
>the container doesn't own the objects, and the objects have
>identity, then you need pointers. There are cases where you'd
>want to delete the objects because the container is going out of
>scope, but they are fairly rare.
My point is that the code above should not be considered in
isolation. It is only correct under a set of specific circumstances
of which you have mentionned some examples or if somewhere in the code
there's a loop that deletes every single pointers in the vector before
it goes out of scope. (or if you are lazy and this is a short
lived program, you could rely on the OS freeing all the memory when
the program exit but that's not an approach I would recommend).
So the original question should be: "Which is better:"
vector<record *> r;
r.push_back(new record(x,y));
// ... do stuff
while(!r.empty())
{
delete(r.back());
r.pop_back();
}
OR:
>> >> > vector<record> r;
>> >> > r.push_back(record(x,y));
// do stuff
These two code snippets are much more directly comparable although we
are still missing the definition of record and the first snippet is
not exception safe. Looking at them now, I would say that even a C++
newbie would notice the additional complexity required in the first
case. If we add exception safety to the first snippet, it becomes
even more complicated.
>> IMNSHO, that should be your default solution. I.e. unless you
>> know that this is not suitable for this particular case, use
>> this form.
>
>Let me see if I've got that straight. You should use this form
>except when you shouldn't use it:-). (I'm being a bit facetious
>there---I basically agree with you.
Exactly. Use the default solution unless you know that you shouldn't
use it in this case. e.g.:
-Use standard containers with value semantic unless you know you must
use pointers.
-Don't (micro-)optimize unless you know you must.
-Use local variable unless you know you must use a global
-Use automatic object unless you know you must use free store.
-Make reference arguments const unless you know they must not be.
-Use standard containers unless you know you they don't meet your
requirements.
-Use vector by default unless you know you shouldn't in this case.
-Drive on the normal side of the road unless you know this is a
one-way street and you can safely drive in the other lane.
(I am sure someone will jump on me for these :-)
Don't get me wrong. All of these default solutions can be broken.
In fact, they very often must be broken. But if one does, one should
be able to explain why.
>I think that learning the various "standard" categories of
>objects should have precedence. Until you understand the
>difference between value types and entity types, it doesn't make
>sense to discuss the question.
That's also what I mean. Kai-uwe answer was very extensive and quite
correct but for learners, I quite like a practical and simpler
approach of considering a "standard" solution first and deviate from
it if you know it you must. Actually, even for experienced
developpers, I think it's good to first consider the obvious default
solution before going for a more complex pattern.
A la prochaine
Yan
|