如何防止对象的不必要副本

时间:2015-09-28 17:50:36

标签: c++

我有一个执行以下操作的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对象以某种方式移动 - 从{1}}从不同内存位置的对象调用而不是原始operator QString()对象在AData的{​​{1}}。常规构造函数被调用一次。但可能是copy-elision只是在内存中移动了相同的对象。

但是,当我在operator[]中定义三个/五个规则之一(如析构函数)而不更改任何其他内容(并且析构函数本身不执行任何操作)时,{{在ADocument的{​​{1}}中构造的SAME OBJECT(相同的内存位置)上调用1}}。

即使我实现了所有可思考的构造函数和运算符(移动,复制,赋值......),它们中的任何一个都被调用但结果是相同的 - 只创建了一个对象。

这里发生了什么?我想了解它。

此外,如何更改此实现,以便尽可能提高性能和内存效率(=最小副本等)?或者也许我真的在这里没什么担心,我看到的只是一些编译器优化?

1 个答案:

答案 0 :(得分:1)

  

这里发生了什么?我想了解它。

您正在体验复制省略

如果将未命名的临时文件复制或移动到相同类型的变量中,则允许编译器直接在变量中构造对象并跳过复制或移动操作。

您可能遇到此情况的另一种情况是从函数返回具有自动存储持续时间的变量。