I would like to store the value that is passed to the constructor in a static set returned by a static function. It seems that the insertion is successful, but when it reach the end of the scope of the constructor it disappear. I have reproduced it in a simple example:
// container.hh
#pragma once
#include <vector>
#include <set>
class container {
public:
container(const int& s);
static std::set<int, std::less<int>>& object_set_instance();
};
#include "container.hxx"
// container.hxx
#pragma once
#include "container.hh"
#include <iostream>
container::container(const int& s)
{
auto set = object_set_instance();
set.insert(s);
std::cout << "Size " << set.size() << "\n";
}
std::set<int, std::less<int>>& container::object_set_instance()
{
static std::set<int, std::less<int>> s;
return s;
}
#include "container.hh"
#include <iostream>
int main()
{
auto a = container(42);
auto b = container(21);
auto b1 = container(51);
auto b2 = container(65);
auto b3 = container(99);
}
Output :
Size 1
Size 1
Size 1 // Size never change
Size 1
Size 1
Why doesn't the set's size change ?
CodePudding user response:
auto set = object_set_instance();
If you use your debugger to inspect what set
is, you will discover that it's a std::set
and not a std::set&
reference. Effectively, a copy of the original std::set
is made (object_set_instance()
returns a reference, only to copy-construct a new object that has nothing to do with the referenced one), and the next line of code modifies the copy, and it gets thrown away immediately afterwards.
This should be:
auto &set = object_set_instance();
A debugger is a very useful tool for solving these kinds of Scooby-Doo mysteries, and it would clearly reveal what's going on here. If you haven't yet had the opportunity to learn how to use one, hopefully this will inspire you to take a look, and join Mystery, Inc. as a member in good standing.