C++rapidjson:GenericValue::IsNull在任何情况下都返回false
C++ rapidjson: GenericValue::IsNull is returning false in any case
在我们的项目中发现一个神秘的问题后,我仍然感到震惊。
我们意识到调用HasMember("字符串")是在执行额外的查找。因此,出于性能原因,我们更改了它。
主要思想是:
而不是调用HasMember,然后预处理引用,如:
rapidjson::Document d;
d.Parse<0>(json);
if(d.HasMember("foo"))
{
const rapidjson::Value& fooValue = d["foo"];
// do something with fooValue
}
更改为:
rapidjson::Document d;
d.Parse<0>(json);
const rapidjson::Value& fooValue = d["foo"];
if( !fooValue.IsNull() )
{
// do something with fooValue
}
这非常好,我们节省了执行两次查找,而不是只执行一次。然而,问题来了。
如果您开始研究rapidjson如何实现nullvalue(在查找失败时默认返回),您将看到以下代码:
//! Get the value associated with the object's name.
GenericValue & operator[](const Ch* name) {
// Check
if (Member * member = FindMember(name)) {
return member->value;
} else {
// Nothing
static GenericValue NullValue;
return NullValue;
}
}
// Finder
const GenericValue & operator[] (const Ch* name) const {
// Return
return const_cast<GenericValue &> (* this)[name];
}
因此,如果没有找到成员,我们将返回一个局部静态变量。乍一看,这听起来可能足够好了,但由于这是通过引用返回的,很容易导致隐藏的错误。
假设有人更改了静态NullValue的引用。这将导致所有对IsNull的进一步调用(在查找之后)都将失败,因为NullValue更改为另一种类型,甚至更改为随机内存。
那么,你喜欢什么?你认为这是一个好的null模式示例吗?
我很困惑,我喜欢返回默认null值的想法,但由于没有作为const返回,这很危险。而且,即使我们在所有情况下都将其作为const返回,开发人员仍然可以使用const_cast(但我不认为,如果他们这样做了,他们会对此负责)。
我想听听其他像这样的案例和例子。如果有人能在rapidjson代码下给出一个真正的解决方案,那将是非常棒和令人惊叹的。
社区早就提出了这种设计的缺陷。由于operator[]
还需要一个非常量版本,因此不可能保持静态变量的完整性。
因此,这个API在RapidJSON的新版本中进行了更改。operator[]
只是为不存在的密钥断言。如果不确定密钥是否存在,最好使用
MemberIterator FindMember(const Ch* name);
ConstMemberIterator FindMember(const Ch* name) const;
并将该值与MemberEnd()
进行比较,以检查密钥是否存在。这里也记录了这一点。
此外,请注意,RapidJSON已经转移到GitHub。许多问题已经得到解决。如果可能的话,请使用最新版本。非常感谢。
附言:我是RapidJSON的作者。
- QueryWorkingSet总是返回false
- 当返回类型声明为 ListNode 时,我们是否可以返回 false<T>*
- 等于在 c++ 中返回 false
- strcmp 对于相等的字符序列返回 false
- C++ - 负数和正数之间的比较返回 false
- protobuf 的 ParseFromString 函数返回 false
- 递归函数始终返回 false
- 为什么 GetExitCodeThread() 在这里返回 FALSE?
- MFC 的 OnInit() 函数中的返回 true 和返回 false 有什么区别
- if 语句在条件为真时返回 false
- 为什么 std::isnan() 对于具有 NAN 值的双变量返回 false
- is_lock_free() 在升级到 MacPorts gcc 7.3 后返回 false
- 在 winapi 回调函数上返回 FALSE 时出现意外行为(循环被跳过?
- 如果数组中有重复的数字,如何返回'false'?
- std::is_array 当它应该返回 false 时返回 true
- 为什么pyarg_parsetuple总是返回false
- 删除为应该在哈希表中的记录返回 false 的函数
- Vulkan 和 glfwVulkanSupported() 总是返回 false
- tf2_ros::Buffer::canTransform() 为现有转换返回 False
- 出于某种原因,布尔值返回 false