简介:我正在编写一个 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_nodeas some smart pointer to a LegacyNode, I would have to pass&head_node.get()tobuild_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/
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
通过rubykoans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,
您将如何构建一个简单的Sinatra应用程序?我正在制作,我希望该应用具有以下功能:“应用程序”更像是一个包含所有信息的管理仪表板。然后另一个应用程序将通过REST访问信息。我还没有创建仪表板,只是从数据库中获取东西session和身份验证(尚未实现)您可以上传图片,其他应用可以显示这些图片我已经使用RSpec创建了一个测试文件通过Prawn生成报告目前的设置是这样的:app.rbtest_app.rb因为我实际上只有应用程序和测试文件。到目前为止,我已经将Datamapper用于ORM,将SQLite用于数据库。这是我的第一个Ruby/Sinatra项目,所以欢迎任何和所有建议-我应
我想知道Ruby用来在命令行打印这些东西的输出流:irb(main):001:0>a="test"=>"test"irb(main):002:0>putsatest=>nilirb(main):003:0>a=>"test"$stdout是否用于irb(main):002:0>和irb(main):003:0>?而且,在这两次调用之间,$stdout的值是否有任何变化?另外,有人能告诉我打印/写入这些内容的Ruby源代码吗? 最佳答案 是的。而且很容易向自己测试/证明。在命令行试试这个:ruby-e'puts"foo"'>test.