防止不必要的C ++函子对象的副本 [英] Prevent unnecessary copies of C++ functor objects

查看:117
本文介绍了防止不必要的C ++函子对象的副本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类,它累积有关一组对象的信息,并且可以充当函子或输出迭代器。这允许我做如下事情:

I have a class which accumulates information about a set of objects, and can act as either a functor or an output iterator. This allows me to do things like:

std::vector<Foo> v;
Foo const x = std::for_each(v.begin(), v.end(), Joiner<Foo>());

Foo const x = std::copy(v.begin(), v.end(), Joiner<Foo>());

现在,理论上,编译器应该能够使用复制检测和返回值优化,以便只有一个 Joiner 对象需要被创建。然而,在实践中,函数使一个副本操作,然后将其复制回结果,即使在完全优化的构建。

Now, in theory, the compiler should be able to use the copy elision and return-value optimizations so that only a single Joiner object needs to be created. In practice, however, the function makes a copy on which to operate and then copies that back to the result, even in fully-optimized builds.

如果我创建函子作为左值,编译器创建两个额外的副本而不是一个:

If I create the functor as an lvalue, the compiler creates two extra copies instead of one:

Joiner<Foo> joiner;
Foo const x = std::copy(v.begin(), v.end(), joiner);

如果我将模板类型强制转换为引用,它会在引用中传递, ,并返回对(现在销毁的)临时副本的悬挂引用:

If I awkwardly force the template type to a reference it passes in a reference, but then makes a copy of it anyway and returns a dangling reference to the (now-destroyed) temporary copy:

x = std::copy<Container::const_iterator, Joiner<Foo>&>(...));

我可以通过使用引用状态而不是函数中的状态本身来使这些副本便宜在 std :: insertionter 的风格,导致这样的:

I can make the copies cheap by using a reference to the state rather than the state itself in the functor in the style of std::inserter, leading to something like this:

Foo output;
std::copy(v.begin(), v.end(), Joiner<Foo>(output));

但是这使得不可能使用不可变对象的 t很好。

But this makes it impossible to use the "functional" style of immutable objects, and just generally isn't as nice.

有没有办法鼓励编译器删除临时副本,或者让它通过一个引用并返回同一个引用? / p>

Is there some way to encourage the compiler to elide the temporary copies, or make it pass a reference all the way through and return that same reference?

推荐答案

你偶然抱怨了< algorithm> 。对于他们可以用函子做什么没有限制,所以你的问题的答案是否定的:没有办法鼓励编译器删除副本。 它不是(总是)编译器,它的库实现。他们只是想传递函数的价值(想想std ::排序做一个qsort,传递函数的值递归调用等)。

You have stumbled upon an often complained about behavior with <algorithm>. There are no restrictions on what they can do with the functor, so the answer to your question is no: there is no way to encourage the compiler to elide the copies. It's not (always) the compiler, it's the library implementation. They just like to pass around functors by value (think of std::sort doing a qsort, passing in the functor by value to recursive calls, etc).

还遇到了每个人都使用的确切解决方案:有一个函子保持对状态的引用,所以所有副本指的是相同的状态,当这是需要的。

You have also stumbled upon the exact solution everyone uses: have a functor keep a reference to the state, so all copies refer to the same state when this is desired.

我发现这个讽刺:


但是这使得不可能使用不可变对象的功能风格,而且通常不是那么好。 / p>

But this makes it impossible to use the "functional" style of immutable objects, and just generally isn't as nice.

...因为这整个问题是基于你有一个复杂的有状态函子,其中创建副本是有问题的。如果你使用功能风格的不可变对象,这将是一个非问题 - 额外的副本不会是一个问题,他们吗?

...since this whole question is predicated on you having a complicated stateful functor, where creating copies is problematic. If you were using "functional" style immutable objects this would be a non-issue - the extra copies wouldn't be a problem, would they?

这篇关于防止不必要的C ++函子对象的副本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆