putting pointers to objects in a set

Started by
21 comments, last by DevFred 14 years, 8 months ago
Can some C++ guru confirm I'm invoking undefined behavior?
#include <set>

class Player
{
    // exact contents irrelevant
};

int main()
{
    Player* a = new Player();
    Player* b = new Player();
    std::set<Player*> players;

    players.insert(a);
    players.insert(b);

    players.clear();
    delete b;
    delete a;
}
I don't want to spoil the fun, but it's obviously got to do with pointers ;)
Advertisement
Yup, I think so.
On the flip side, can anyone name a machine *offhand* on which this won't behave as the author intended?

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Quote:
5.9 Relational operators

If two pointers point to elements of the same array or one beyond the end of the array, the pointer to the object with the higher subscript compares higher. [...] Other pointer comparisons are unspecified.

Yup, there you have it. But what exactly does "unspecified" mean in this context? Is that less strong than "undefined"?

As I understand it, putting pointers to objects in an unordered_set should be ok, right?
Quote:
5.10 Equality operators

Pointers to objects or functions of the same type (after pointer conversions) can be compared for equality. Two pointers of the same type compare equal if and only if they are both null, both point to the same function, or both represent the same address.
Quote:Original post by DevFred
Quote:
5.9 Relational operators

If two pointers point to elements of the same array or one beyond the end of the array, the pointer to the object with the higher subscript compares higher. [...] Other pointer comparisons are unspecified.
Yup, there you have it. But what exactly does "unspecified" mean in this context? Is that less strong than "undefined"?
Much less strong than 'undefined':

Unspecified behavior also means that the code is also completely legal C++, but compilers may interpret it differently. The difference between implementation-defined behavior and unspecified behavior is that the compiler vendor is not required to describe what their particular compiler does. For example, when you cast an integer to an enum , the resulting enum value may in some cases be unspecified. (source)

However, an interesting side effect of that definition of 'unspecified', is that your original code is indeed legal C++. Or, in other words, C++ doesn't guarantee the order of elements in your set-of-pointers, but it does guarantee that an ordering will exist (and may differ between implementations).

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Hm, but as I understand it, "unspecified" could also mean that p < q always returns false if p and q do not point to elements of the same array, because the implementation can do whatever it wants...
Or, worse, it could always return true, making it not define a partial order at all.
Why is C++ not properly defined / specified? Makes it so much more complex, with the only result that compiler builders can do what they want?
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
Because defining and specifying the behavior of a lot of that behavior would have performance impacts. Ex: indexing out array bounds with a pointer is undefined behavior. In order to define that behavior, you would then need to track the array bounds and the pointer aliases and do comparisons against those bounds.
Quote:Original post by DevFred
Can some C++ guru confirm I'm invoking undefined behavior?

*** Source Snippet Removed ***

I don't want to spoil the fun, but it's obviously got to do with pointers ;)


Yup. Failing to return a specific value from a function of type int is bad, and in the case of main() it should be explicitly return EXIT_SUCCESS; *nod nod nod*.

Yes, ok, the hidden < operator is wrong in this context. But memory has been flat since Windows 3.1 died, anywhere I've even been, so ordering by address is something I no longer worry about. It's all a big array now really.

On the other hand, there is rarely reason to order things by address. You just wouldn't use set for that, you're paying for useless ordering. Which in itself bugs me; I don't know why a set, which is not a term that implies ordering to me, has to be ordered in the first place. They should have been called set and ordered_set. Yeah. Someone fix the standard.

This topic is closed to new replies.

Advertisement