- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个类,它累积有关一组对象的信息,并且可以充当仿函数或输出迭代器。这使我可以执行以下操作:
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>());
现在,理论上,编译器应该能够使用 copy elision and return-value optimizations这样只需要创建一个 Joiner
对象。然而,在实践中,该函数会创建一个拷贝以对其进行操作,然后将其复制回结果,即使是在完全优化的构建中也是如此。
如果我将仿函数创建为左值,编译器会创建两个额外的拷贝而不是一个:
Joiner<Foo> joiner;
Foo const x = std::copy(v.begin(), v.end(), joiner);
如果我笨拙地将模板类型强制为一个引用,它会传入一个引用,但无论如何都会复制它并返回一个对(现已销毁的)临时拷贝的悬空引用:
x = std::copy<Container::const_iterator, Joiner<Foo>&>(...));
我可以通过在 std::inserter
风格的仿函数中使用对状态的引用而不是状态本身来使拷贝便宜,导致这样的事情:
Foo output;
std::copy(v.begin(), v.end(), Joiner<Foo>(output));
但这使得无法使用不可变对象(immutable对象)的“函数式”风格,而且通常也不是那么好。
有没有办法鼓励编译器省略临时拷贝,或者让它一直传递引用并返回相同的引用?
最佳答案
您偶然发现了一个经常被提示的 <algorithm>
行为.他们可以用仿函数做什么没有限制,所以你的问题的答案是否定的:没有办法鼓励编译器省略拷贝。 它(总是)不是编译器,而是库实现。他们只是喜欢按值传递仿函数(想想 std::sort 执行 qsort,按值将仿函数传递给递归调用等)。
您还偶然发现了每个人都在使用的确切解决方案:让仿函数保持对状态的引用,因此在需要时所有拷贝都引用相同的状态。
我觉得这很讽刺:
But this makes it impossible to use the "functional" style of immutable objects, and just generally isn't as nice.
...因为这整个问题的前提是你有一个复杂的有状态仿函数,创建拷贝是有问题的。如果您使用的是“函数式”样式的不可变对象(immutable对象),这将不是问题 - 额外的拷贝不会成为问题,对吗?
关于c++ - 防止不必要的 C++ 仿函数对象复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58774493/
我是一名优秀的程序员,十分优秀!