【问题标题】:Perform a copy of Document object of rapidjson执行rapidjson的Document对象的拷贝
【发布时间】:2014-05-07 14:50:59
【问题描述】:

我正在创建一个类,我想在一个方法中返回我的类。我的班级有一个rapidjson::Document 对象。

以前的问题可以看这里:LNK2019: "Unresolved external symbol" with rapidjson

正如我所发现的,rapidjson 会阻止您执行 Document 对象的任何类型的副本,然后包含 Document 对象的类的默认副本失败。我正在尝试定义自己的复制构造函数,但我需要执行对象的副本。 I saw a way 假设使用 .Accept() 方法复制对象,但在 rapidjson::Document 类中返回了很多错误:

错误 C2248:'无法访问在类 `rapidjson::GenericDocument' 中声明的私有成员

这是我的复制构造函数:

jsonObj::jsonObj(jsonObj& other)
{
    jsonStr = other.jsonStr;
    message = other.message;

    //doc = other.doc;
    doc.Accept(other.doc);

    validMsg = other.validMsg;
}

我发现 in the code of the library(第 52-54 行)那个“Copy constructor is not permitted”。

这是我的课:

class jsonObj {
    string jsonStr;
    Document doc; 

public:
    jsonObj(string json);
    jsonObj(jsonObj& other);

    string getJsonStr();
};

方法:

jsonObj testOBJ()
{
    string json = "{error:null, message:None, errorMessage:MoreNone}";
    jsonObj b(json);
    return b; //It fails here if I return a nested class with a rapidjson::Document in it. Returning NULL works
}

那么如何执行Document元素的拷贝呢?

【问题讨论】:

  • 阅读wiki user guide for rapidjson 的此页面上的文档,在我看来,您需要重新考虑如何编写jsonObj 类。如果您想实际制作 rapidJson 文档的副本,则需要分配一个新文档,然后将旧文档显式复制到新文档,从而生成具有相同数据的两个不同文档。因此,您需要为jsonObj 提供一个复制构造函数、赋值等。您可能需要重新考虑您的架构和 rapidJson 的使用。
  • @RichardChambers 我已经有一个复制和分配构造函数,但是我不知道如何复制Document 对象而不每次都解析 json 字符串。我需要一个包含 rapidjson 库的类,因为我正在制作一个 C++ 库,并且我需要使用包装器在外部公开 json 解析器,所以我需要通过一个包含 Document 的方法返回我的类。 =/
  • 我认为复制文档对象的唯一方法是进行解析,否则您会遇到带有重复指针的深拷贝与浅拷贝以及谁拥有什么内存分配问题。 rapidJson 似乎是为任何特定文档的单个实例设计的,因此您的包装器将需要使用移动语义而不是复制语义。在我看来,您正试图违背 rapidJson 的架构和设计,这就是为什么我建议您重新考虑您的架构或寻找 rapidJson 的替代方案。
  • 在阅读了上一个问题和这个问题之后,我开始认为@RichardChambers 对他的评论是正确的,另一方面,我正在考虑另一件事,而不是在嵌套的class 中使用文档在没有Document 成员的情况下创建它,并在确定范围时创建它,这可能会允许另一个Document instance
  • 对于那些感兴趣的人,Document 现在支持 C++11 移动语义(截至提交 1950efd6760fc89a074ae5b989e560edded92578),由您真诚提供。但是,它不会帮助 OP 为包含按值的 Document 的对象实现复制构造函数。

标签: c++ visual-c++ visual-studio-2012 rapidjson


【解决方案1】:

必须使用 (const) 引用作为返回类型(尝试在创建者类中存储新文档),您不能复制文档,即不能按值返回,因为您隐式尝试使用禁用的复制构造函数

【讨论】:

    【解决方案2】:

    在新文档上使用 CopyFrom 方法:

    rapidjson::Document inDoc;    // source document
    rapidjson::Document outDoc;   // destination document
    outDoc.CopyFrom(inDoc, outDoc.GetAllocator());
    

    tested this approach 对输出文档所做的更改对输入文档没有影响。确保为 CopyFrom 方法提供了输出文档的分配器。

    【讨论】:

    • 它也适用于非文档类型,只要对象可以转换为值。 Value v = ...; outDoc.CopyFrom(v, outDoc.GetAllocator());
    【解决方案3】:

    我创建了这个方法来复制文档对象,它对我来说很好:

    static void copyDocument(rapidjson::Document & newDocument, rapidjson::Document & copiedDocument) {
        rapidjson::StringBuffer strbuf;
        rapidjson::Writer<rapidjson::StringBuffer> writer(strbuf);
        newDocument.Accept(writer);
        std::string str = strbuf.GetString();
        copiedDocument.Parse<0>(str.c_str());
    }
    

    【讨论】:

    • 解析并不快。
    【解决方案4】:

    存储库https://github.com/rjeczalik/rapidjson 拥有DeepCopy patch,它可能会帮助您将一个文档复制到另一个文档中。

    【讨论】:

    • 谢谢,但第 447 行的补丁没有t worked for me (error on IsString`)在尝试执行复制时:doc.Accept(other.doc);
    • 想创建一个测试用例(例如,在 gist.github.com 或 pastebin 中)?
    • IsString 问题是另一个问题。您的解决方案有效;谢谢。
    猜你喜欢
    • 1970-01-01
    • 2015-09-14
    • 2010-11-19
    • 2018-02-26
    • 2016-09-27
    • 2012-06-19
    • 2019-11-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多