构建和返回复杂结果数据集的有效方法

时间:2018-02-20 12:40:37

标签: c++ c++11 move-semantics

通常,函数构造复杂的结果,例如vector个对象。在简单的,未经优化的C ++中,这很容易导致许多中间副本。我想知道如何构建这样一个对象以避免不必要的副本。

以下功能显示了我想做什么以及如何天真地实现它。对db的调用只是伪代码,大致显示函数的结构。

vector<Result> get_result(Query q){
    vector<Result> ret;
    db.start_query(q); 
    while(db.has_more()){
        int i = db.get_next_int("i");
        string s = db.get_next_str("s");
        Result result(i, s);
        ret.push_back(result); // copy on push
    }
    return ret; // copy on return
}

考虑到现代C ++ 11或更新版本,我应该如何实现这种功能,并移动语义?可以更改函数的签名,以便vector<Result>可以成为捕获结果的输入参数。

2 个答案:

答案 0 :(得分:1)

您所能做的就是使用emplace_back就地构建result,从而避免复制,因为NRVO也可能没有复制品。

ret.emplace_back(i, db.get_next("s"));

无论如何,由于VS2017中vector的大小为32字节,所以它非常轻量级,移动操作很快,因此如果您使用的数据库可能并不重要。

答案 1 :(得分:0)

在C ++ 17中甚至不保证命名的返回值优化。

因此,如果您想确定不会获取不必要的值副本,请通过引用传递返回向量:

void get_result(Query q, vector<Result>& foo)

并写

foo = std::move(ret);

作为最终陈述。

我一直小心避免return std::move(ret):请参阅When should std::move be used on a function return value?