gpt4 book ai didi

c++ - 将 C++ 接口(interface)写入动态分配的 C 结构

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:00:14 24 4
gpt4 key购买 nike

简介:我正在编写一个 C++11 应用程序,它广泛使用了遗留的 C 代码库。遗留代码中一个非常常见的模式是存在一些 struct LegacyStruct这是通过诸如

之类的方法构造和销毁的
build_struct(LegacyStruct *L, int arg1, int arg2)
free_struct(LegacyStruct *L)

基本上是构造函数/析构函数。遗留代码库中的所有权模型非常 unique_ptr -esque,所以我的目标是将它包装在一个内存安全的、支持 RAII 的包装类中,如下所示:

class Wrapper {
public:
Wrapper::Wraper() : handle() {}
Wrapper::Wrapper(int same_arg1, int same_arg2);
Wrapper::Wrapper(const Wrapper &W) = delete;
Wrapper::Wrapper(Wrapper &&W) : handle(std::move(W.handle)) {}
//copy operator= and move operator= analogously
private:
std::unique_ptr<LegacyStruct, custom_deleter> handle;

哪里custom_deleter电话 free_struct沿着 this question 的路线,或者只是 std::default_delete 的部分特化对于 LegacyStruct .无论如何,到目前为止一切顺利,我认为这是一种常见的设计模式,非常适合我的需要。

我的问题:在处理表单的链表类型结构的情况下,我无法调整此模式

typedef struct LegacyNode {
int stack_allocated_data;
OtherStruct *heap_allocated_data;
LegacyNode *next;
} LegacyNode;

同样,遗留代码库中的所有权模型是 unique_ptr -esque:链表的唯一所有权,即适当释放它的责任。同理还有对应的free_node(LegacyNode *N)释放的功能heap_allocated_data ,如有必要,然后释放节点本身。

但施工情况却大不相同。将有一个看起来像的函数

build_list(LegacyNode **L, int *count_p, int other_args){
LegacyNode *newnode;

//code allocating newnode and populating its fields

//...and then:
newcut->next = *L;
*L = newcut;
(*count_p)++;
}

并调用 build_list看起来像

int list_count = 0;
LegacyNode *L = (LegacyNode *) NULL;

build_list(&L, &list_count, 99);

编辑/澄清: build_list是代码库中的静态非导出函数,我通过调用其他调用 build_list 的函数来访问它可能好几次。

因此,我喜欢写一个ListWrap存储头节点和列表长度的类,并具有与 Wrapper 相同的复制/移动运算符上面,即列表本身的唯一所有权,它可以移动但不能复制等。

但是,我的理解是智能指针在这种情况下不是一个选项。与 head_node作为指向 LegacyNode 的智能指针,我必须传递 &head_node.get()build_list ,这会破坏智能指针不变量/所有权?

就目前而言,我的包装类包含一个指向头节点的原始指针,该方法返回头节点的地址以供 build_list 使用。 , 一个遍历列表调用 free_node 的析构函数, 和基于谓词的 erase -type 方法,只删除某些元素。

当然,修改和清除链表是 CS-101 级别的东西,但我仍然设法浪费了几个小时来编写它并且到处都是内存泄漏!此外,遗留代码库中还有其他几个使用几乎相同的链表结构,所以我希望能够将其转换为一个类模板,该模板可以专门用于类型和删除器,并继承以提供类型-具体方法。

谢谢

最佳答案

However, my understanding is that smart pointers are not an option in this case. With head_node as some smart pointer to a LegacyNode, I would have to pass &head_node.get() to build_list, which would corrupt the smart pointer invariants/ownership?

是的,这是正确的,因为 build_list 会覆盖该内存位置的对象,从而破坏智能指针的内存。但是还有另一种方法,您可以使用现有指针构造一个 std::unique_ptr!

因此,不是 ListWrap 分配它自己的对象,而是让 build_list 分配对象,然后只获取指针并用 RAII 将它们包装起来。

class ListWrap {
public:
ListWrap(LegacyNode* head, int count);
//...
private:
std::unique_ptr<LegacyNode, &free_node> handle;
int count;
};

ListWrap::ListWrap(LegacyNode* head, int count) : handle{ head }, count{ count } {}

关于c++ - 将 C++ 接口(interface)写入动态分配的 C 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41003323/

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