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