为什么序列运算算法谓词是通过复制传递的
Why the sequence-operation algorithms predicates are passed by copy?
我想知道为什么函数是通过复制传递给algorithm
函数的:
template <typename T> struct summatory
{
summatory() : result(T()) {}
void operator()(const T& value)
{ result += value; std::cout << value << "; ";};
T result;
};
std::array<int, 10> a {{ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 }};
summatory<int> sum;
std::cout << "nThe summation of: ";
std::for_each(a.begin(), a.end(), sum);
std::cout << "is: " << sum.result;
我期待着以下输出:
求和:1;1.2.3.5.8.13;21;34;55;是:143
但是sum.result
包含0
,这是在ctor中指定的默认值。实现所需行为的唯一方法是捕获for_each
:的返回值
sum = std::for_each(a.begin(), a.end(), sum);
std::cout << "is: " << sum.result;
之所以会发生这种情况,是因为函子是通过复制而不是通过引用传递给for_each
的:
template< class InputIt, class UnaryFunction >
UnaryFunction for_each( InputIt first, InputIt last, UnaryFunction f );
因此,外部函子保持不变,而内部函子(它是外部函子的副本)会更新,并在执行算法(实时演示)后返回,因此在完成所有操作后,结果会再次被复制(或移动)。
这样做肯定有充分的理由,但我并没有真正意识到这个设计的基本原理,所以我的问题是:
- 为什么序列运算算法的谓词是通过复制而不是引用传递的
- 在通过引用的方法之前,通过复制的方法有什么优势
这主要是由于历史原因。在98年,当整个算法被纳入标准参考文献时,出现了各种各样的问题。这最终通过C++03及更高版本的核心和库DR得到了解决。此外,合理的ref包装器和实际工作的绑定仅在TR1中才到达。
那些在早期的C++98中尝试使用具有使用ref params或return的函数的算法的人可以回忆起各种各样的麻烦。自写算法也容易遇到可怕的"引用到引用"问题。
传递价值至少效果很好,几乎没有造成太多问题——boost在早期就有ref和cref来帮助你解决需要调整的地方。
这纯粹是猜测,但。。。
让我们暂时假设它通过引用const来实现。这意味着您的所有成员都必须是可变的,并且运算符必须是const。这感觉不太"对"。
让我们暂时假设它通过引用非常数来实现。它会调用一个非常数运算符,成员可以很好地处理。但是,如果你想传递一个特别的对象呢?就像绑定操作的结果一样(即使C++98也有丑陋而简单的绑定工具)?或者类型本身只做你需要的一切,然后你就不需要对象了,只想像for_each(b,e,my_functor());
一样调用它?这是行不通的,因为临时变量不能绑定到非常量引用。
因此,也许不是最好的,但最不坏的选择是按值取值,在过程中尽可能多地复制它(希望不要太频繁),然后在完成后,从for_each返回它。这可以很好地处理总结对象的较低复杂性,不需要添加诸如引用const方法之类的可变内容,也可以处理临时对象。
但是YMMV,委员会成员也很可能如此,我想最终是对他们认为最有可能适合大多数用例的内容进行了投票。
也许这是一个变通方法。捕获函子作为引用,并在lambda 中调用它
std::for_each(a.begin(), a.end(), [&sum] (T& value)
{
sum(value);
});
std::cout << "is: " << sum.result;
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 使用strcpy将char数组的元素复制到另一个数组
- 是否可以初始化不可复制类型的成员变量(或基类)
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到
- 复制列表初始化的隐式转换的等级是多少
- GCC本机矩阵运算库
- 当从函数参数中的临时值调用复制构造函数时
- 有可能在Armadillo中复制MATLAB circshift方法吗
- 复制几乎为空的数组的最快方法
- 以下示例中如何避免代码复制?C++/库达
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 不能将复制初始化与隐式转换的多个步骤一起使用
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 为什么复制而不是移动数据元素?
- 文件系统:复制功能的速度秘诀是什么
- 为什么序列运算算法谓词是通过复制传递的