【发布时间】:2018-02-20 12:40:37
【问题描述】:
通常,一个函数会构造一个复杂的结果,例如对象的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> 可以成为捕获结果的输入参数。
【问题讨论】:
-
如果你有信息,
ret.reserve(final_size)可能会避免使用重新分配的副本。 -
只是猜测,但我会把钱花在
start_query上,这比你在这段代码中可以做的任何事情都要多。 -
没有“返回时复制”,
return ret;语句选择vector的移动构造函数,因为ret被视为rvalue 这里。有关详细信息,请参阅 C++11 标准的第 12.8/32 节。我要添加的唯一内容是按照 Jarod42 的建议添加到reserve向量内存并切换到emplace_back以防止复制result。 -
通过引用返回。这减少了复制大型结构的内容的需要。您也可以使用智能指针传递。
-
@ThomasMatthews 什么?你听说过复制省略和移动语义吗? OP 的
get_result函数是一个经典示例,其中按值返回无疑是最佳实践。
标签: c++ c++11 move-semantics