set erase of null and nonexistent elements

P

puzzlecracker

I have a std::set<A *> and assume that operator () is implemented to
establish relative order and for equality

What does standard or popular implementation dictate of the following
example:

#include<set>
#include "A.h"

using std::set


int main(int argc, char **argv)
{
std::set<A *> aSet;
A *nullA=0;
A *a=new A("NOT HERE")

set.insert(new A("something"))
//here is the list of operations I am
aSet.erase(nullA);
aSet.erase(a);

//clean up and return
return 0;
}

How do standard containers (instantiated with some pointer to user-
defined type) behave in the presence of null pointer?

Thanks
 
K

Kai-Uwe Bux

puzzlecracker said:
I have a std::set<A *> and assume that operator () is implemented to
establish relative order and for equality

Huh?

Anyway, the code below does not make any use of operator(). It uses
std::less<A*>. If that is not specialized in A.h, the remarks below apply.
If it is specialzed, you have to make sure it is a strict total ordering.

What does standard or popular implementation dictate of the following
example:

#include<set>
#include "A.h"

using std::set


int main(int argc, char **argv)
{
std::set<A *> aSet;
A *nullA=0;
A *a=new A("NOT HERE")

set.insert(new A("something"))
//here is the list of operations I am
aSet.erase(nullA);

null-op: nullA is not in the set.
aSet.erase(a);

null-op: a is not in the set.
//clean up and return
return 0;
}

How do standard containers (instantiated with some pointer to user-
defined type) behave in the presence of null pointer?

If the null-pointer is an element of the set, it will be removed. Otherwise,
trying to remove it, is a null-op. This holds, unless std::set<> is used
with a custom predicate or a specialized version of std::less<>.


Best

Kai-Uwe Bux
 
P

puzzlecracker

Anyway, the code below does not make any use of operator(). It uses
std::less<A*>. If that is not specialized in A.h, the remarks below apply.
If it is specialzed, you have to make sure it is a strict total ordering.

I meant something else entirely. I was refering to algorithms, such as
find_if where passed predicate, which implemented operator () for
comparison. I assume set uses operator == to locate elements of UDT.
Correct me if am wrong.


null-op: nullA is not in the set.


null-op: a is not in the set.

Well, if we insert a null pointer into a set, wouldn't it cause an
error whenever the container would try to invoke its member.

Wait, perhaps an std container doesn't do that, hence no errors are to
be seen, then how does find work?
 
K

Kai-Uwe Bux

puzzlecracker said:
I meant something else entirely. I was refering to algorithms, such as
find_if where passed predicate, which implemented operator () for
comparison. I assume set uses operator == to locate elements of UDT.
Correct me if am wrong.

You are wrong: std::set<> uses std::less<> to decide whether two elements
are equal. The idea is that a == b can be characterized as neither a < b
nor b < a. In fact, operator== is not used by std::set<> at all.

Well, if we insert a null pointer into a set, wouldn't it cause an
error whenever the container would try to invoke its member.

Yes. Dereferencing a null-pointer is undefined behavior. That, however, does
not imply that you cannot insert the null-pointer into a set. You just have
to make sure that it does not get dereferenced.

Wait, perhaps an std container doesn't do that, hence no errors are to
be seen, then how does find work?

Post code, so that we can discuss find() or find_if() meaningfully. I don't
trust my crystal ball and can only guess what you are looking at.



Best

Kai-Uwe Bux
 
J

James Kanze

puzzlecracker wrote:

[...]
Yes. Dereferencing a null-pointer is undefined behavior. That,
however, does not imply that you cannot insert the
null-pointer into a set. You just have to make sure that it
does not get dereferenced.

Also, std::set<T*> never dereferences the pointers it contains.
Let's face it, this is pure template code, with no partial
specializations or whatever, so the code is exactly the same for
pointers and for non-pointers.

Of course, if you explicitly specialize std::less< A* > so that
it does dereference the pointer, you'll get into deep trouble if
the pointer is null. But that would be just stupid (unless your
goal is obfuscation). The standard defines a full ordering on
pointers (using std::less, but not with <), and requires
std::set to use this ordering by default. A reader who sees a
set instantiated without a custom ordering function has a right
to expect that this ordering is what is used, and not something
else. (If this ordering isn't appropriate, and it often isn't,
then you should says so explicitly, by providing an ordering
argument to the template instantiation.)
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top