具有容器成员的类的RAII习语

时间:2016-01-12 07:31:42

标签: c++ c++11 containers raii

我对以下代码中描述的类有以下问题:

#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. 我想知道它是否符合RAII标准。如果没有,我该如何修改它的实现来实现它。

  2. 我想确认地图Collector::m_container存储在免费商店中。元组键和小部件都存储在免费商店吗?

  3. foo是否会泄漏内存?

  4. 分配的资源按什么顺序销毁?

2 个答案:

答案 0 :(得分:4)

  1. 是的,您的每个对象都是RAII对象,这意味着当它被销毁时会释放所有获取的资源。 Widget没有获得任何资源,因此没有任何资源可供免费使用。同样适用于Coord。通常,只要模板参数是标准库模板就是RAII。因此std::shared_ptr<Widget>是RAII对象,std::map< std::tuple<int, int>, std::shared_ptr<Widget>>也是如此。

  2. m_container是结构数据成员。形式上,如果在堆栈上创建Collector,则m_container将在堆栈中,如果使用Collector创建new,则m_collection将在免费商店。但是,std::map的标准库定义通常可以通过创建&#34;映射节点&#34;使用newstd::map对象本身只能保存一些(固定)指向某些节点(根对象等)的指针。总的来说,它拥有的几乎所有内存都在免费商店中,正如你所说,但正式实体m_container可以在内存中的任何地方。

  3. foo不会泄漏任何内存,构造的每个对象都是RAII对象,因此所有内存都会在销毁时释放。

  4. 您可以保证foo中的五个不同的局部变量按照相反的构造顺序销毁。但是,在更详细的细节层面上,它是实现定义的,例如,std::map节点被销毁的顺序。

答案 1 :(得分:-1)

  1. RAII没有严格的合规标准。你的问题不清楚。

  2. 这是无法回答的,因为程序甚至无法编译。

  3. 有些工具可以为您检测内存泄漏(或至少某种类型),学会使用它们!此外,您可以简单地将调试输出添加到析构函数,并将它们与构造函数中的类似调试输出进行匹配。确保你抓住所有构造函数!

  4. 请参阅问题3的答案。