Scope of a set allocated on the stack

Hi
I am looking for someone kind enough to send me a refresher on memory allocation in c++ in the following case. The following code seems to work. However "std::set<int> a_set" is allocated on the stack and I would expect it to be freed when we exit init and it runs out of scope?
Thank you for your help

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct MyStruct {
 
 void init() {
  auto it = my_map_.find(2);                                                                               
  if(it == my_map_.end()) {
    std::set<int> a_set;            
    a_set.insert(3);
    auto ret = my_map_.insert(make_pair(2, a_set));
   } else {
     it->second.insert(3);
   }
 }

 std::map<int, std::set<int> > my_map_ 
}
Last edited on
and I would expect it to be freed when we exit init and it runs out of scope?
a_set is freed after it runs out of scope. Copy of it is stored in map.
Thank you for your response.

So are you saying that when I do my_map_.insert(make_pair(2, a_set)); the copy constructor for std::set is being called?

Is it a deep copy or shallow copy?

What if i was not storing int but instead i was storing another struct like the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct AnotherStruct {
int a;
};

struct MyStruct {
 
 void init() {
    std::set<AnotherStruct> a_set;
    AnotherStruct a_other_struct;
    a_other_struct.a=3;            
    a_set.insert(a_other_struct);
    my_map_.insert(make_pair(2, a_set));
 }

 std::map<int, std::set<AnotherStruct> > my_map_ 
}


What would happen?
Thanks again for your help.
Last edited on
All containers uses copy constuctor of their elements to perform a copy of them, so if copy constructor is properly implemented (as it is in all standard library and primitive types) it would be a deep copy.
Structs (and classes) has a default copy constructor which does a good job unless you have pointer/non-copyable member inside.

Also you can use my_map_.emplace(2, a_set) to construct elements in place and avoid posiible unnesesary copies.
Thanks a lot for your reply.

One more question. When I do my_map_.insert(make_pair(2, a_set));
Is it make_pair or insert that does call copy constructor for a_set?

You also anticipated my next question. The question was the following:
a_set gets copied via its copy constructor when inserted into m_map_.
Each element of the a_set gets also copied via their copy constructor.
Isn't inefficient? In that case are we better of allocating a_set into the heap and manipulate its pointer like something along the following code?
1
2
3
4
5
6
7
8
9
10
11
12
struct MyStruct {
 
 void init() {
    std::set<AnotherStruct*> * a_set = new std::set<AnotherStruct*>;
    AnotherStruct * a_other_struct = new AnotherStruct();
    a_other_struct->a=3;            
    a_set->insert(a_other_struct);
    my_map_.insert(make_pair(2, a_set));
 }

 std::map<int, std::set<AnotherStruct>* > my_map_ 
}


What do you think of heap vs. stack so we diminish the number of time copies are being made?

But you thankfully pointed me to emplace. Would the code with emplace look like the following? ( i am still struggling with c++).

Thank you for your help

1
2
3
4
5
6
7
8
9
10
11
12
13
struct MyStruct {
 
 void init() {
  auto it = my_map_.find(2);                                                                               
  if(it == my_map_.end()) {
    my_map_.emplace(3, std::set<int>(1,2))
   } else {
     it->second.insert(3);
   }
 }

 std::map<int, std::set<int> > my_map_ 
}

Last edited on
One more question. When I do my_map_.insert(make_pair(2, a_set));
Is it make_pair or insert that does call copy constructor for a_set?
make_pair calls copy constructor of a_set. insert would call copy constructor of resulting pair which calls copy constructor of set if it wasn't temporary. In this case move constructors are called.

Yes, you can do emplace like you said, but you should avoid temporary copies (in your example temporary set is created and then moved into place)
correct way: my_map_.emplace(3, {1, 2});. This will create in place pair of integer 3 and set of two numbers: 1 and 2.
Thank you so much.
Topic archived. No new replies allowed.