【发布时间】:2012-08-07 13:54:36
【问题描述】:
考虑下面的代码。
std::vector<result_data> do_processing()
{
pqxx::result input_data = get_data_from_database();
return process_data(input_data);
}
std::vector<result_data> process_data(pqxx::result const & input_data)
{
std::vector<result_data> ret;
pqxx::result::const_iterator row;
for (row = input_data.begin(); row != inpupt_data.end(); ++row)
{
// somehow populate output vector
}
return ret;
}
当我在考虑是否可以期待返回值优化 (RVO) 发生时,我发现 this answer by Jerry Coffin [强调我的]:
至少在 IMO,这通常是一个糟糕的主意,但不是出于效率原因。这是一个糟糕的主意,因为所讨论的函数通常应该写成一个通用算法通过迭代器产生它的输出。几乎所有接受或返回容器而不是在迭代器上操作的代码都应该被认为是可疑的.
不要误会我的意思:有时传递类似集合的对象(例如字符串)是有意义的,但对于引用的示例,我认为传递或返回向量是一个糟糕的主意。
有一些 Python 背景,我非常喜欢生成器。实际上,如果它是 Python,我会将上面的函数编写为生成器,即避免在其他任何事情发生之前处理整个数据的必要性。比如这样:
def process_data(input_data):
for item in input_data:
# somehow process items
yield result_data
如果我正确解释了 Jerry Coffins 的注释,这就是他的建议,不是吗?如果是这样,我该如何在 C++ 中实现它?
【问题讨论】:
-
只返回向量,完全没问题。 (N)RVO 很可能会处理这个问题,并且在 C++11 中,移动语义将在 (N)RVO 不处理时执行。另外,
return process_data(get_data_from_database());。遗憾的是,C++ 没有yield功能。 :( -
“几乎所有接受或返回容器而不是在迭代器上操作的代码都应该被认为是可疑的。”我会反对这一点。这当然是一个很好的一般建议,但是让代码独立于容器类型的愿望经常被误导,而且它们除了语法之外不是很容易互换......
标签: c++ iterator generator coroutine yield-keyword