构建和 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
构造result
in-place从而避免复制,而且return上也可能因为NRVO而没有复制.
ret.emplace_back(i, db.get_next("s"));
而且无论如何,由于 VS2017 中 vector
的大小是 32 字节,所以它非常轻量级并且移动操作很快,因此如果你使用数据库,这可能并不重要。
通常,一个函数会构造一个复杂的结果,例如 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
构造result
in-place从而避免复制,而且return上也可能因为NRVO而没有复制.
ret.emplace_back(i, db.get_next("s"));
而且无论如何,由于 VS2017 中 vector
的大小是 32 字节,所以它非常轻量级并且移动操作很快,因此如果你使用数据库,这可能并不重要。