Adding to a map of unique pointers

Hi,
I am trying to convert my program to use smart pointers but am having trouble creating a map of unique pointers. The map contains sf::image and uses the file name as a key. This prevents the same image being loaded in more than once. The map uses unique pointers because the list should have ownership of the data (sf::Image).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class ResourceManager
{
private:
  std::unordered_map<std::string, std::unique_ptr<sf::Image>()> m_images;
...
}

std::shared_ptr<sf::Image> ResourceManager::GetImage(const std::string& _filename)
{
  if (m_images.find(_filename) == m_images.end())
  {
    std::unique_ptr<sf::Image> m_image(new sf::Image());
    if (!m_image->loadFromFile("resources/images/" + _filename))
    {
      std::cout << "Error: Cannot load file: " << "resources/images/" << _filename << std::endl;
      return std::shared_ptr<sf::Image>();
    }  

    m_images.insert(std::make_pair(_filename, std::move(m_image)));

    return std::shared_ptr<sf::Image>(std::move(m_image));
  }
  else
  {
    return std::shared_ptr<sf::Image>(std::move(m_images.at(_filename)));
  }
}


The problem is with the insert method. I think it is because you cant assign a unique pointer with move as it would make it not unique.

Would it be better to store sf::image in the list but still return shared_ptr?
 
std::unordered_map<std::string, sf::Image> m_images;


Thanks in advance.
Last edited on
A unique_ptr means: The pointee is owned by this pointer. No other pointer shares in ownership. It doesn't make sense to use shared_ptr if you're using unique_ptr. The two represent different ownership strategies.


Would it be better to store sf::image in the list but still return shared_ptr?

Store an sf::Image and return a regular pointer or reference. You could, of course, store a unique_ptr in the map and return a regular pointer or a reference to the image, but I don't see a good reason for an additional level of indirection.
Thanks for your response. I think I understand smart pointers a bit more now.

Would you ever return a smart pointer? or do you only return raw pointers and convert them into smart pointers if necessary. eg:

1
2
3
4
5
6
7
8
9
10
int data = 5;

int*  GetData(void)
{
  return &data;
} 

...

std::weak_ptr<int> data1(GetData());

I would say it is rather simple:

Use unique_ptr if you don't want to share the data.
Use shared_ptr if you want to share the data.

If you use the combination unique_ptr/raw pointer you are still in the situation where the life time of the object may be shorter than the use of it.

So:
Would you ever return a smart pointer?
Yes.
or do you only return raw pointers and convert them into smart pointers if necessary.
No.
Thanks for clearing that up. I should be able to finish converting my project to use smart pointers now.
Topic archived. No new replies allowed.