首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >高效函数风格(C++11 ok)

高效函数风格(C++11 ok)
EN

Stack Overflow用户
提问于 2012-02-29 14:37:06
回答 5查看 630关注 0票数 0

假设我有以下内容:

代码语言:javascript
复制
struct point
{
  double x;
  double y;
  double z;
};

我可以写下以下代码:

代码语言:javascript
复制
void point_mult(point& p, double c) { p.x *= c; p.y *= c; p.z *= c; }
void point_add(point& p, const point& p2) { p.x += p2.x; p.y += p2.y; p.z += p2.z; }

因此,我可以执行以下操作:

代码语言:javascript
复制
point p{1,2,3};
point_mult(p, 2);
point_add(p, point{4,5,6});

这不需要point的副本,只需要两个构造,即构造point{1,2,3}和构造point{4,5,6}。我相信,即使point_addpoint_multpoint{...}位于不同的编译单元中(即不能内联),这一点也适用。

但是,我想以一种更函数式的方式编写代码,如下所示:

代码语言:javascript
复制
point p = point_add(point_mult(point{1,2,3}, 2), point{4,5,6});

我如何编写point_multpoint_add,使其不需要副本(即使point_multpoint_add位于不同的编译单元中),或者函数风格在C++中不是很有效?

EN

回答 5

Stack Overflow用户

发布于 2012-02-29 15:34:11

让我们忽略这个问题的隐含谬误(即复制自动意味着效率降低)。让我们忽略这样一个问题:是否真的会发生任何复制,或者是否所有复制都会被任何不太像样的编译器省略掉。让我们从表面上看:这可以在不复制的情况下完成吗?

是的,这可能是r-value引用的唯一其他合法用途(尽管之前被忽略的规定使得这个用例值得怀疑):

代码语言:javascript
复制
point &&point_mult(point &&p, double c);

当然,这只会绑定到临时对象。因此,您将需要一个替代版本的l值:

代码语言:javascript
复制
point &point_mult(point &p, double c);

关键是,您可以按原样传递引用,或者作为对临时变量的引用,或者作为对l值的引用。

票数 4
EN

Stack Overflow用户

发布于 2012-02-29 14:56:16

它可以用非常难看的模板元编程来完成。例如,eigen使用模板,因此像matrix1 + matrix2 * matrix3这样的表达式不需要创建任何临时变量。它的工作原理是,矩阵的+*运算符不返回Matrix对象,而是返回某种矩阵表达式对象,该对象根据表达式参数的类型进行模板化。然后,此矩阵表达式对象可以仅在需要时计算表达式的某些部分,而不是创建临时对象来存储子表达式的结果。

实际上,实现这一点可能会变得相当混乱。如果你感兴趣,可以看看Eigen的源码。Boost的uBlas也做了类似的事情,尽管它不像eigen那样广泛。

票数 3
EN

Stack Overflow用户

发布于 2012-02-29 15:01:16

一种有效的(且通用的)技术是表达式模板。你可以阅读一个很好的介绍性解释here

它很难实现,而且是基于模板的,你不能使用单独的编译单元,但它非常有效。符号计算中一个有趣的应用是解析: Boost.Spirit在解析的基础上构建了非常高效的解析器。

C++11 auto关键字有助于在实际编程任务中使用,在处理复杂类型时一如既往,请参阅this other answer。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9494619

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档