우리 프로젝트에서 신비로운 문제를 발견 한 후에도 여전히 충격을 받았습니다.C++ rapidjson : GenericValue :: IsNull은 어떤 경우에도 false를 반환합니다.
HasMember ("string")를 호출하면 추가 검색이 수행된다는 것을 알았습니다. 따라서 성능상의 이유로 변경합니다.
주요 아이디어는 다음과 같습니다에 변경
rapidjson::Document d;
d.Parse<0>(json);
if(d.HasMember("foo"))
{
const rapidjson::Value& fooValue = d["foo"];
// do something with fooValue
}
: HasMember를 호출하고 이후에 같은 기준을 미리 캐시의 대신
이 제법 괜찮은
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의 참조를 변경한다고 상상해보십시오. 이로 인해 NullValue가 다른 유형으로 변경되었거나 임의의 메모리로 변경 되었기 때문에 IsNull을 찾는 이후의 모든 추가 호출이 실패합니다.
그래서, 너 뭐야? 이 패턴이 좋은 null 패턴이라고 생각하십니까?
혼란 스럽습니다. 기본 null 값을 반환한다는 생각은 좋아하지만 const로 반환되지 않았으므로 위험합니다. 그리고 우리가 const로 모든 경우에 그것을 반환하더라도, devs는 여전히 const_cast를 사용할 수 있습니다. (그렇다고하더라도 그렇게한다면 책임을지지 않습니다.)
나는이 사례와 다른 사례를 듣고 싶습니다. 그리고 누군가 rapidjson 코드 아래서 진짜 해결책을 줄 수 있다면 근본적으로 멋지고 놀랍습니다.
'if (! d.IsNull())'이 (가) if (! fooValue.IsNull())이어야합니다. – Narek
오른쪽! 수정되었습니다. – dmayola