我有一个rapidjson包装,做以下的不必要的副本:如何防止物体
class ADocument
{
void setJson(const char *data) { m_D.parse(data); }
AData operator[](const char *key) const
{
const rapidjson::Value *value = rapidjson::Pointer(key).Get(m_D);
if(value)
return AData(value);
else
return AData(&m_D);
}
private:
rapidjson::Document m_D;
};
和AData
类是这样的:
class AData
{
public:
Adata(const rapidjson::Value *val) : m_Value(val) {}
operator QString() const { return m_Value.IsString() ? m_Value.GetString() : QString(); }
private:
const rapidjson::Value *m_Value;
};
而且整个事情是这样调用:
ADocument doc;
doc.setJson("{\"Hello\":{\"Hello\":\"test\"}}");
QString str = doc["/Hello/Hello"];
时
str
变为 “测试”
。
现在,通过调试这个代码我发现该AData
对象以某种方式移动 - 的operator QString()
会从在不同的存储器位置的对象比原始AData
对象调用中的ADocument
的operator[]
构造。正则构造函数被调用一次。但可能是copy-elision只是在内存中移动相同的对象。
然而,当我定义的规则的三/ 5方法之一,如AData
析构函数不改变任何东西(和析构函数什么也不做本身),那么operator QString()
上调用同一对象(同一内存位置),其在ADocument
的operator[]
中构建。
即使当我实现了所有可想象的构造函数和运算符(move,copy,assign ...)时,它们中的任何一个都不会被调用,但结果是相同的 - 只创建一个对象。
这是怎么回事?我想了解它。
此外,如何改变这个实现,以便尽可能提高性能和内存效率(=最小副本等)?或者,也许我真的很担心没有什么,我所看到的仅仅是一些编译器优化?
什么是AConstData? –
@AlanStokes对不起,错字。我从我的源代码复制了我实际上有两个类AData和AConstData的代码。我用后者进行了一些测试,但它们都是相同的。 – Resurrection
声音像复制elision正在按预期工作,有什么问题?我认为你不用担心,应该让编译器完成它的工作。 –