Rapidjson 返回对文档值的引用

Rapidjson returning reference to Document Value

我在使用以下方法时遇到了一些问题,我需要一些帮助来弄清楚我做错了什么。

我想 return 引用文档中的值。我从函数外部传递文档,这样当我将 json 文件读入其中时,我不会 "lose it".

const rapidjson::Value& CTestManager::GetOperations(rapidjson::Document& document)
{
    const Value Null(kObjectType);

    if (m_Tests.empty())
        return Null;

    if (m_current > m_Tests.size() - 1)
        return Null;

    Test& the_test = m_Tests[m_current];

    CMyFile fp(the_test.file.c_str()); // non-Windows use "r"
    if (!fp.is_open())
        return Null;

    u32 operations_count = 0;

    CFileBuffer json(fp);
    FileReadStream is(fp.native_handle(), json, json.size());

    if (document.ParseInsitu<kParseCommentsFlag>(json).HasParseError())
    {
        (...)
    }
    else
    {
        if (!document.IsObject())
        {
            (...)
        }
        else
        {
            auto tests = document.FindMember("td_tests");
            if (tests != document.MemberEnd())
            {
                for (SizeType i = 0; i < tests->value.Size(); i++)
                {
                    const Value& test = tests->value[i];

                    if (test["id"].GetInt() == the_test.id)
                    {
                        auto it = test.FindMember("operations");
                        if (it != test.MemberEnd())
                        {
                            //return it->value; is this legitimate?
                            return test["operations"];
                        }

                        return Null;
                    }
                }
            }
        }
    }

    return Null;
}

我是这样称呼的:

Document document;
auto operations = TestManager().GetOperations(document);

当我在函数内部检查 test["operations"] 的值时,我可以看到我期望的一切(调试代码从居留代码中删除)。

当我检查函数外部的 returned 值时,我可以看到它是一个数组(我希望如此)。数组中的成员计数也是正确的,但是当打印出来时,我只看到垃圾。

当我 "print" 方法内的字符串的值时,我得到了我所期望的(即格式正确的 json),但是当我在外部执行时,所有键都显示为 "IIIIIIII" 并且不是字符串的值会正确显示。

    rapidjson::StringBuffer strbuf2;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer2(strbuf2);
    ops->Accept(writer2);

由于这不起作用,我决定更改方法以接收值作为参数并像这样对其进行深度复制

u32 CTestManager::GetOperationsEx(rapidjson::Document& document, rapidjson::Value& operations)
{
   (...)

    if (document.ParseInsitu<kParseCommentsFlag>(json).HasParseError())
    {
        (...)
    }
    else
    {
        if (!document.IsObject())
        {
            (...)
        }
        else
        {
            auto tests = document.FindMember("tests");
            if (tests != document.MemberEnd())
            {
                for (SizeType i = 0; i < tests->value.Size(); i++)
                {
                    const Value& test = tests->value[i];

                    if (test["id"].GetInt() == the_test.id)
                    {
                        const Value& opv = test["operations"];

                        Document::AllocatorType& allocator = document.GetAllocator();
                        operations.CopyFrom(opv, allocator);    //would Swap work?
                        return operations.Size();
                    }
                }
            }
        }
    }

    return 0;
}

我是这样称呼的:

Document document;
Value operations(kObjectType);
u32 count = TestManager().GetOperationsEx(document, operations);

但是...我得到了同样的东西!!!!

我知道这会很傻,但我不能动手!

有什么想法吗?

本例中的问题出在 ParseInSitu 的使用上。当任何 GetOperations 存在时,CFileBuffer 就会失去作用域并被清除。因为当文件缓冲区消失时 json 正在原位解析,所以数据也消失了。