构建和 ​​return 复杂结果数据集的有效方法

Efficient way to build and return a complicated result dataset

通常,一个函数会构造一个复杂的结果,例如 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> 可以成为捕获结果的输入参数。

在 C++17 中甚至不能保证命名 return 值优化。

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

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?

你所能做的就是用emplace_back构造resultin-place从而避免复制,而且return上也可能因为NRVO而没有复制.

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

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