29

I am getting a size of 1. Shouldn't it be 4? I am inserting the addresses of integers into the sets.

void func(set<int*>& s1, set<int*>& s2, int a)
{
    s1.insert(&a);
    s2.insert(&a);
}

int main()
{
    set<int*> s1, s2;

    int a = 1, b = 2, c = 3, d = 4;
    func(s1, s2, a);
    func(s1, s2, b);
    func(s1, s2, c);
    func(s1, s2, d);

    cout<<"  s1.size = "<<s1.size()<<"  s2.size = "<<s2.size()<<endl;
}
Boann
  • 48,794
  • 16
  • 117
  • 146
instance
  • 1,366
  • 15
  • 23
  • 14
    Really? 3 people think this question should be closed because it "does not appear to be about programming"? – user200783 Jul 05 '17 at 09:40
  • 1
    Surprisingly, GCC (`g++ -W -Wall -Wextra -Werror`) and Clang compile this code without any warnings. – pts Jul 05 '17 at 11:29
  • 1
    @user200783 _"... within the scope defined in the [help center](https://stackoverflow.com/help/on-topic)."_ – YSC Jul 05 '17 at 11:59
  • 8
    This is neither "a problem that can no longer be reproduced" nor "a simple typographical error". Voted to reopen. – user200783 Jul 05 '17 at 14:26

2 Answers2

44

&a inside func is the address of the local parameter a, not the address of the original variable (a, b, c or d), which:

  1. Can take various kind of values between different calls of func;
  2. Becomes an invalid pointer once you reach the end of the scope in which a is declared (the end of func here).

In your case, since you do nothing but calling func 4 times in a row, the address of this parameter happens to not change, which is why you get a size of 1 (you insert the same pointer 4 times).

This behavior is implementation defined (thanks @Rakete1111) since sets will need to compare invalid pointers.

Accessing the pointed element through s1 or s2 (e.g. **s1.begin()) is undefined behavior though.

Holt
  • 36,600
  • 7
  • 92
  • 139
28

The parameter a is passed by value, that means what you're inserting is the address of the local parameter copied from the arguments. a will be constructed everytime when func is called, their addresses might be same or different; nothing is guaranteed.

And it's worth noting that the parameter a will be destroyed when get out of the function, then the pointers inserted will become dangled.

You should make it pass-by-reference, then the addresses of the arguments (i.e. the variable a, b, c, d in main()) will be inserted. These addresses are different, and won't become dangled inside the body of main().

void func(set<int*>& s1, set<int*>& s2, int& a)
{
    s1.insert(&a);
    s2.insert(&a);
}

LIVE

songyuanyao
  • 169,198
  • 16
  • 310
  • 405