-4

I have the following questions about the class described in the code below:

#include <vector>
#include <tuple>
#include <map>
using namespace std;

class Widget
{
public:
    Widget( int x, int y, int z ) : m_x{x}, m_y{y}, m_z{z} {}

private:
    int m_x, m_y, m_z;
};

class Coord {
public:
    Coord( int x, int y, int z ) : p{x}, q{y}, r{z} { }
    std::tuple<int,int> get_tuple() { return std::make_tuple(p, q); }

    int x() { return p; }
    int y() { return q; }
    int z() { return r; }

private:
    int p, q, r;
};

class Collector
{
public:
    Collector(const std::vector<Coord>& pool) { collect(pool); };

    void collect(const std::vector<Coord>& pool)
    {
        for ( auto v : pool )
        {
            tuple<int,int> key = v.get_tuple();
            auto value = make_shared<Widget>(v.x(), v.y(), v.z());
            m_container.insert(make_pair(key, value));
        }
    }

private:
    map< tuple<int,int>, shared_ptr<Widget> > m_container;
};

int foo()
{
    Coord a{0,0,1};
    Coord b{0,1,0};
    Coord c{1,0,0};
    vector<Coord> pool{a, b, c};
    auto col = std::make_shared<Collector>( pool );
    return 0;
}
  1. I would like to know if it is RAII compliant. If not, how do I modify its implementation to make it so.

  2. I wanted to confirm that the map Collector::m_container is stored on the free-store. Are both the tuple-keys and the Widgets both stored on the free-store?

  3. Does foo leak memory?

  4. In what order are the allocated resources destroyed?

Chris Beck
  • 15,614
  • 4
  • 51
  • 87
unshul
  • 269
  • 3
  • 16

2 Answers2

4
  1. Yes, every one of your objects is an RAII object, meaning that when it is destroyed it releases any and all acquired resources. Widget doesn't acquire any resources, so it has nothing to free. Similarly for Coord. Generally, standard library templates will be RAII as long as the template parameters are. So std::shared_ptr<Widget> is an RAII object, as is std::map< std::tuple<int, int>, std::shared_ptr<Widget>>.

  2. m_container is a structure data member. Formally, if a Collector is created on the stack, then m_container will be on the stack, and if a Collector is created with new, then m_collection will be on the free-store. However, the standard library definition of std::map will generally work by creating "map nodes" using new, and the std::map object itself will only hold a (fixed) number of pointers to some of those nodes (root objects or such). So as a whole, almost all of the memory it owns is on the free-store as you say, but formally the entity m_container can be anywhere in memory.

  3. foo does not leak any memory, every object that is constructed is an RAII object, and so all the memory is released upon its destruction.

  4. You are guaranteed that the five different local variables in foo are destroyed in the reverse order of construction. However, at a finer level of detail, it is implementation-defined, for instance, in what order std::map nodes are destroyed.

Chris Beck
  • 15,614
  • 4
  • 51
  • 87
-1
  1. There are no strict compliance criteria for RAII. Your question is unclear.

  2. This can't be answered, because the program doesn't even compile.

  3. There are tools that detect memory leaks (or at least some kind of them) for you, learn to use them! Further, you could simply add debug output to the destructors and match them against similar debug output in the constructors. Make sure that you catch all constructors though!

  4. See answer for question 3.

Ulrich Eckhardt
  • 16,572
  • 3
  • 28
  • 55