c++ - 为什么序列操作算法谓词是通过拷贝传递的?

标签 c++ c++11 stl-algorithm

我想知道为什么仿函数通过复制传递给 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;

我期待以下输出:

The summation of: 1; 1; 2; 3; 5; 8; 13; 21; 34; 55; is: 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 );

所以外部仿函数保持不变,而内部仿函数(它是外部仿函数的拷贝)被更新并在执行算法(live demo)后返回,所以结果被复制(或移动)完成所有操作后再次


这样做一定有充分的理由,但我并没有真正意识到这种设计的基本原理,所以我的问题是:

  • 为什么序列运算算法的谓词通过复制而不是引用传递?
  • 与引用传递方法相比,复制传递方法有何优势?

最佳答案

这主要是出于历史原因。在 98 年,当整个算法的东西被纳入标准引用时,出现了各种各样的问题。这最终通过 C++03 及更高版本的核心和库 DR 得到了解决。明智的 ref-wrappers 和实际工作的绑定(bind)也只在 TR1 中出现。

那些尝试在早期 C++98 中使用具有使用 ref 参数或返回的函数的算法的人可以记忆起各种麻烦。自行编写的算法也容易遇到可怕的“引用引用”问题。

按值传递至少工作得很好,几乎不会产生很多问题——而且 boost 很早就有 ref 和 cref 来帮助您找出需要调整的地方。

关于c++ - 为什么序列操作算法谓词是通过拷贝传递的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42721683/

相关文章:

c++ - 有没有办法通过引用模拟向下转换

c++ - 关于 unique_ptr 中原始指针的类型

c++ - STL 计数算法返回不正确的值。

c++ - 使用back_inserter从结构的单个成员创建 vector

c++ - LNK 2001 单例上未解析的外部符号

c++ - 如何在源代码中设置程序执行的优先级?

c++ - 将函数添加到先前链接的文件后出现多定义链接器错误

c++ - 无法使用 vector::插入 "no instance of overloaded function..."

arrays - C++11 段错误试图动态地将数组(<algorithm>)复制到向量中

C++ 浮点表示