gpt4 book ai didi

c++ - 通过 C 接口(interface)分配和释放资源的正确用法

转载 作者:行者123 更新时间:2023-11-30 02:01:56 25 4
gpt4 key购买 nike

C++ 程序通常必须处理 C 库,这些库提供用于分配和释放资源的自由函数。为简化此示例,考虑两个 C 函数,如 get_resource()free_resource()

考虑一个对象在其生命周期的某个时刻获取任何资源,并在对象被销毁或由于构建过程中的错误而未完全构建时自动释放它。

获得这种自动化的理想/简短/简单的习语是什么?下面是一个想法,但它使对象不能正确地默认移动。除了在析构函数中释放内存或检查构造函数中的错误以进行回滚之外,还有什么更好的方法吗?

struct Object {
void* my_get_resource() { // might be called from the constructor or any other point
return get_resource();
}

Object() : up(&resource, &del) {
resource = my_get_resource();
/* init all the stuff, but this init might fail at _many_ points */
}
//~Object() { if (resource) free_resource(resource); } // I don't like: collides with del and is not called if my_get_resource() is called from the constructor and the init process fails for some reasons

private:
void *resource = nullptr;
static void del(void ** ) noexcept {
if (*resource) { free_resource(resource); }
}
unique_ptr < void*, decltype(&del) > up; // RAII: almost good, sadly that makes Object not moveable properly without redefining the move constructor properly


};

最佳答案

显然您想要一个可移动的 RAII 包装器。

然后只需定义一个移动构造函数并声明一个 protected 或私有(private)的复制构造函数和复制赋值运算符。如果您不打算支持当前的 Visual C++,那么您可以将复制构造函数和复制赋值运算符声明为已删除。

这涉及在构造函数中检查错误并在析构函数中清理,这与您的要求不符......

Is there anything better which does not imply freeing memory from within the destructor or checking errors in the constructor to do rollbacks?

简而言之,这些要求通常与您发布的代码所指示的目标不兼容。

即使您使用 unique_ptr 来完成这项工作,它的工作方式也是通过在构造函数中检查错误并在析构函数中清理,这与您的(极不现实的)要求直接不符。

以下是如何开始“手动”做事:

bool hopefully( bool const c ) { return c; }
bool throwX( string const& s ) { throw std::runtime_error( s ); }

class Resource
{
private:
void* pResource;

Resource( Resource const& ); // Add "= delete" if all compilers support it.
Resource& operator=( Resource const& ); // Ditto.

public:
void* theValue() const { return pResource; } // Use problem-specific name.

~Resource()
{
if( pResource != 0 )
{
::freeResource( pResource );
}
}

Resource()
: pResource( ::getResource() )
{
hopefully( pResource != 0 )
|| throwX( "Resource::<init>: getResource failed" );
}

Resource( Resource&& other )
: pResource( other.pResource )
{
other.pResource = 0;
}
};

您可以添加移动赋值运算符。

并且您可以将其归纳为Handle 类模板。


免责声明:未经测试的现成代码,未经编译器处理。

关于c++ - 通过 C 接口(interface)分配和释放资源的正确用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13675090/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com