Move semantics of RapidJSON

来源:互联网 发布:网络看电视直播 编辑:程序博客网 时间:2024/05/17 20:34

RapidJSON 的设计有一个特性, 进行赋值操作时, 不是把源value复制(copy)到目的 value, 而是转移(move)到目的value.
例如

Value a(123);Value b(456);b = a; // a becomes a Null value, b becomes number 123.

这里写图片描述

这样的设计的目的是 为了提高性能. 对于固定大小的JSON类型(Number, True, False, Null), 复制很简单快捷. 而对于可变大小的类型(String, Array, Object), 复制时会产生大量不容易被察觉的开销. 尤其是当我们需要创建一个临时的值, 把它复制给另一个变量, 然后析构它.
若使用正常的复制 语义:

Document d;Value o(kObjectType);{    Value contacts(kArrayType);    // Adding elements to contacts array.    // ...    o.AddMember("contacts", contacts, d.GetAllocator(); // deep clone contacts(may be with lots of allocations)    // destruct contact}

这里写图片描述

o 需要分配跟contacts 大小一样的缓冲区, 做深度复制, 然后析构contacts . 这样会产生大量不必要的内存分配/释放 和内存复制.
有一些方案可以避免实质的复制这些数据, 如引用计数, 垃圾回收等等.
为了使RapidJSON简单和快速, 我们选择使用转移语义来进行赋值. 这与std::auto_ptr类似, 都是在赋值时转移拥有权. 转移比复制简捷地多, 它只需 析构原来的值, 把源值memcpy() 到目的值, 最后再把源值 设为Null类型.

使用转移语义, 上面的例子变成:

Document d;Value o(kObjectType);{    Value contacts(kArraryType);    // Adding elements to contacts array.    o.AddMember("contacts", contacts, d.GetAllocator()); // Just memcpy() of contacts itself to the value of new member(16 bytes)    // contacts became Null here. Its destructiong is trivial.}

这里写图片描述

转移语义和临时值
有时, 我们想直接构造一个临时变量传给”转移”函数, 如PushBack() , AddMember() . 由于临时对象不能直接转化成正常的值引用, 我们可以调用Move() 函数

Value a(kArrayType);Document::AllocatorType& allocator = document.GetAllocator();// a.PushBack(Value(42), allocator); // Compiling errora.PushBack(Value().SetInt(42), allocator); // fluent APIa.PushBack(Value(42).Move(), allocator); // same as above

翻译原文: http://rapidjson.org/md_doc_tutorial.html#MoveSemantics

0 0
原创粉丝点击