Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;以RAII样式管理资源附件数组_C++_Raii - Fatal编程技术网

C++ C++;以RAII样式管理资源附件数组

C++ C++;以RAII样式管理资源附件数组,c++,raii,C++,Raii,下面是演示我试图解决的问题的幻想代码(请参阅注释//problem-);基本上,在做了一些可能抛出的事情之后,如何确保分离一堆资源句柄 #include <initializer_list> // from a C-style API extern int create_thingie(); // returns non-zero resource handle extern int create_widget(); // returns non-zero resource han

下面是演示我试图解决的问题的幻想代码(请参阅注释
//problem-
);基本上,在做了一些可能抛出的事情之后,如何确保分离一堆资源句柄

#include <initializer_list>

// from a C-style API
extern int create_thingie(); // returns non-zero resource handle
extern int create_widget(); // returns non-zero resource handle
extern void attach_thingie(int widget_handle, int thingie_handle);
extern void detach_thingie(int widget_handle, int thingie_handle);
extern void delete_thingie(int handle); // deletes a thingie unless still attached
extern void delete_widget(int handle);

// RAII wrapper for thingies
class thingie {
    int resource_handle;
public:
    thingie() : resource_handle{create_thingie()} {}
    thingie(const thingie&)=delete;
    thingie& operator=(const thingie&)=delete;
    thingie(thingie&& moved_from)
        : resource_handle{moved_from.resource_handle}
    {
        moved_from.resource_handle = 0;
    }
    thingie& operator=(thingie&&)=delete;
    ~thingie() { delete_thingie(this->resource_handle); }
    inline int get_handle() const
    {
        return this->resource_handle;
    }
};

// RAII wrapper for widgets
// here identical to thingie, but not in my use-case
class widget {
    int resource_handle;
public:
    widget() : resource_handle{create_widget()} {}
    widget(const widget&)=delete;
    widget& operator=(const widget&)=delete;
    widget(widget&& moved_from)
        : resource_handle{moved_from.resource_handle}
    {
        moved_from.resource_handle = 0;
    }
    widget& operator=(widget&&)=delete;
    ~widget() { delete_widget(this->resource_handle); }
    inline int get_handle() const
    {
        return this->resource_handle;
    }
};

class foo {
    widget underlying_widget;
public:
    foo(std::initializer_list<thingie> thingies);
    inline int get_underlying_handle() const
    {
        return this->underlying_widget.get_handle();
    }
};

foo::foo(std::initializer_list<thingie> thingies)
{
    for (thingie const& t : thingies)
        attach_thingie(this->get_underlying_handle(), t.get_handle());
    // do some potentially throwing things
    // PROBLEM - thingies might not get detached, causing resource leak
    for (thingie const& t : thingies)
        detach_thingie(this->get_underlying_handle(), t.get_handle());
}

int main()
{
    foo f1{thingie{}, thingie{}};
    return 0;
}
#包括
//来自C风格的API
extern int create_thingie();//返回非零资源句柄
extern int create_widget();//返回非零资源句柄
外部无效附加内容(内部控件句柄,内部内容句柄);
extern void detach_thingie(int widget_handle,int thingie_handle);
extern void delete_thingie(int handle);//删除内容,除非仍然附加
extern void delete_小部件(int句柄);
//拉伊包装纸
阶级思想{
int-resource_句柄;
公众:
thingie():资源\u句柄{create\u thingie()}{}
thingie(const thingie&)=删除;
thingie&运算符=(const thingie&)=删除;
thingie(thingie&从中移动)
:resource\u handle{已从中移动\u。resource\u handle}
{
已从中移动\u。资源\u句柄=0;
}
thingie&operator=(thingie&&)=删除;
~thingie(){delete_thingie(this->resource_handle);}
内联int get_handle()常量
{
返回此->资源\u句柄;
}
};
//用于小部件的RAII包装器
//这里与thingie相同,但不在我的用例中
类小部件{
int-resource_句柄;
公众:
widget():资源\u句柄{create\u widget()}{}
小部件(常量小部件&)=删除;
小部件和运算符=(常量小部件&)=删除;
小部件(小部件和从中移动(&U)
:resource\u handle{已从中移动\u。resource\u handle}
{
已从中移动\u。资源\u句柄=0;
}
小部件&操作员=(小部件&&)=删除;
~widget(){delete_widget(this->resource_handle);}
内联int get_handle()常量
{
返回此->资源\u句柄;
}
};
福班{
小部件基础的小部件;
公众:
foo(std::初始值设定项\列表内容);
inline int get_底层_handle()常量
{
返回此->基础的_小部件。获取_句柄();
}
};
foo::foo(std::初始值设定项\u列表内容)
{
对于(thingie const&t:thingies)
附加内容(此->获取底层句柄(),t.获取句柄());
//做一些可能会扔东西的事情
//问题-内容可能无法分离,导致资源泄漏
对于(thingie const&t:thingies)
分离(这个->获取底层句柄(),t.获取句柄());
}
int main()
{
foo f1{thingie{},thingie{};
返回0;
}

我的第一个想法是在
foo::foo
中创建一个本地类来表示一个附件(或附件数组),它在构造函数中调用
attach\u thingie
,在析构函数中调用
detach\u thingie
,但我不知道如何以零开销的方式来实现这一点,而不是仅仅在
foo::foo
之外的所有路由中运行分离for循环(即使用
try
/
catch(…)
)。

闻起来像是过早优化。用一个挡块就行了。堆栈展开期间调用析构函数的速度不应快于catch块。如果有疑问,请测量。@Quimby我明白你的意思,可能更像是过早分解,只是因为我想太多了,避免为循环编写两个相同的分离。除非,有没有一种方法可以在没有两个相同循环的情况下使用catch块?但是循环并不完全相同,对吗?如果确实需要,可以将循环重构为一个方法,并使用函数指针调用正确的函数,或者使用一个简单的布尔参数进行附加/分离。因此,将逻辑保留在一个函数中。