Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么序列运算算法谓词是通过副本传递的?_C++_C++11_Stl Algorithm - Fatal编程技术网

C++ 为什么序列运算算法谓词是通过副本传递的?

C++ 为什么序列运算算法谓词是通过副本传递的?,c++,c++11,stl-algorithm,C++,C++11,Stl Algorithm,我想知道为什么函子是通过copy传递给函数的: template <typename T> struct summatory { summatory() : result(T()) {} void operator()(const T& value) { result += value; std::cout << value << "; ";}; T result; }; std::array<int, 10

我想知道为什么函子是通过copy传递给函数的:

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;
之所以发生这种情况,是因为函子是通过复制而不是引用传递给的:

template< class InputIt, class UnaryFunction >
UnaryFunction for_each( InputIt first, InputIt last, UnaryFunction f );
template
每个_的一元函数(先输入,后输入,一元函数f);
因此外部函子保持不变,而内部函子(它是外部函子的副本)更新并在执行算法()后返回,因此在执行所有操作后,结果再次被复制(或移动)


这样做肯定有很好的理由,但我真的没有意识到这种设计的基本原理,所以我的问题是:

  • 为什么序列运算算法的谓词是通过复制而不是引用传递的
  • 在参考传递方法之前,复制传递方法有哪些优势

    • 这主要是出于历史原因。在98年,当所有的algo程序都进入标准参考时,出现了各种各样的问题。这最终通过C++03及更高版本的核心和库DRs得到解决。另外,合理的ref包装器和实际工作绑定只在TR1中到达

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


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

      也许这是一个解决方法。捕获函子作为引用,并在lambda中调用它

      std::for_each(a.begin(), a.end(), [&sum] (T& value) 
          {
              sum(value);   
          });
      
      std::cout << "is: " << sum.result;
      
      std::for_each(a.begin()、a.end()、[&sum](T&value)
      {
      总和(价值);
      });
      
      这纯粹是猜测,但是

      …让我们暂时假设它通过引用const。这意味着您的所有成员都必须是可变的,并且运算符必须是常量。那就是感觉不“对”

      。。。让我们暂时假设它通过引用non-const。它会调用一个非常量操作符,成员只需对其进行精细处理即可。但是如果你想传递一个特别的对象呢?就像绑定操作的结果一样(甚至C++98都有——丑陋而简单的——绑定工具)?或者类型本身只是做你需要的所有事情,之后你不需要对象,只想对每个对象调用
      (b,e,my_functor())?这是行不通的,因为临时变量不能绑定到非常量引用

      因此,也许不是最好的,但最不坏的选择是按值取,在过程中根据需要复制它(希望不要太频繁),然后在完成后,为每个人返回它。这在求和对象的复杂性相当低的情况下可以很好地工作,不需要添加可变的东西,比如对常量的引用方法,并且也适用于临时对象


      但是YMMV,以及委员会成员可能会这样做,我猜这最终是对他们认为最有可能适合大多数用例的内容的投票。

      这很好!,但我并不是在寻找解决方法(但我还是会使用它!):P我只是想知道为什么这个算法的函数签名不是一个referenceHmm。。此链接尝试完成与您相同的操作:。也许可以试试。也许(
      for(inti:a){sum(i);}
      更简单?你能用一些参考来支持吗?在过去的二十年中,我没有听说过任何关于引用的“各种各样的问题”,尤其是C++03中修复的问题,这些问题不能证明在标准库中不使用它是合理的。当然,请在WG21论文中查找缺陷报告。LDR109固定的bind1st和bind2nd只是一个很小的例子我对一个历史性的答案感到失望:(我本想从我的知识中找出一些微妙的性能原因。但这个答案几乎回答了我的两个问题。@BalogPal:我不会真的称之为“引用的所有问题”,特别是因为它在库中有一些错误,并且不是一个根本性的问题,引用可能会使它们不需要在库中使用。@PaperBirdMaster如果您真的想知道性能原因,Chandler的C++Now注释记号可能会提供一些,尽管这肯定不是决策过程的一部分。请注意for_如何返回“ready”object为什么不使用基于范围的循环?
      for(inti:a){sum(i)}
      如果需要,我会使用它,但问题不是如何进行总结,而是关于算法库。例如,如果stl算法将采用非常量引用,那么
      对于每个(…,只需从\u cout\u arg\u到\u std\u out())
      不会编译,不会回答问题,只需使用
      std::acculate
      进行求和,如果需要有状态谓词,则可以始终将状态存储在谓词外部。
      std::for_each(a.begin(), a.end(), [&sum] (T& value) 
          {
              sum(value);   
          });
      
      std::cout << "is: " << sum.result;