Search code examples
c++scopesetcontainersemplace

Scope of an entry added to a c++ set?


Let's say I have a globally scoped set defined as follows:

std::set<Person> people;

I also have a function where I create an instance of the class Person, and add it to the set as follows:

void addEntry() {
    Person p1("kosh", 55);
    people.emplace(p1);
}

The way I understand it, a copy of the object will be created (I can see the copy constructor getting called) and added to the set. Once this function terminates, p1 goes out of scope. But, what is the scope of the copy that is added to the set? Is that determined by the scope of the set?

EDIT 1:

A follow-up question: In such a scenario, is is better to just create p1 in the heap, instead of the stack, and store the pointer in the set?


Solution

  • Lifetime vs scope

    The lifetime of an object is the stretch of time during the program's execution in which the object is alive and can be accessed.

    The scope is the places in the code from which such accesses can be made. See also:

    Scope vs. Lifetime of Variable

    Lifetime of the object in the set

    You're calling the set's emplace() method, with a (reference to) a local variable.

    What does emplace(t) do? Its function is rather uniform across different collections:

    emplace(t): Construct a new object of within the container, as a copy of the object t.

    (I've simplified things bit, e.g. w.r.t. move semantics)

    So, you don't actually put t inside the container. You create a different object; and containers, like std::set(), are implemented so that the lifetime of the created element will be effectively the same as the container's.

    Notes:

    • Remy Lebeau's answer is correct, I just wanted to focus on the method used.
    • Note that std::set is intended for ordered elements; the mathematical notion of a set is better captured by std::unordered_set.

    The follow-up question: Should you use pointers?

    is is better to just create p1 in the heap, instead of the stack, and store the pointer in the set?

    Why would that be better? ... I presume you would say this avoid creating two Person's.

    Well, actually, try something different: Don't create p1 at all; just emplace() using the arguments to the constructor of the Person class, and then there will never be any object other than the one created within the set. So, only a single Person instance is created and then used.