accumulate返回值类型 提醒

accumulate函数

2021-0506修正

参考资料:

https://en.cppreference.com/w/cpp/algorithm/accumulate

函数原型(目前有两个版本):

template< class InputIt, class T >
constexpr T accumulate( InputIt first, InputIt last, T init );

template< class InputIt, class T, class BinaryOperation >
constexpr T accumulate( InputIt first, InputIt last, T init,
                        BinaryOperation op );

从模板函数原型即可见,返回值类型是和参数三的类型一致的。

复制下参考资料里的两个版本实现示例代码:

First version
template<class InputIt, class T>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init)
{
    for (; first != last; ++first) {
        init = std::move(init) + *first; // std::move since C++20
    }
    return init;
}
Second version
template<class InputIt, class T, class BinaryOperation>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init, 
             BinaryOperation op)
{
    for (; first != last; ++first) {
        init = op(std::move(init), *first); // std::move since C++20
    }
    return init;
}

注意的是,如果第三个参数传的只是0,即使序列是double型的数据,返回的也是整型的,

而且,每一步计算的时候都会涉及类型的隐式转换(小数去尾)。并不是说double序列算个总和再去尾,而是每个值都去尾再想加。

写个试验代码:

void funcRun_accumulate()
{
  std::vector<double> vecTest{ 3,3,2.9,8.9 };
  std::cout<< std::accumulate(vecTest.begin(), vecTest.end(), 0.0)<<std::endl;// 17.8
  std::cout << std::accumulate(vecTest.begin(), vecTest.end(), 0) << std::endl;// 16
}

再一个极端点的试验代码,序列值都是不大于1的小数:

void funcRun_accumulate2()
{
  std::vector<double> vecTest{ 0.3,0.3,0.9,0.9 };
  std::cout << std::accumulate(vecTest.begin(), vecTest.end(), 0.0) << std::endl;// 2.4
  std::cout << std::accumulate(vecTest.begin(), vecTest.end(), 0) << std::endl;// 0
}
ps.
另外,这个函数依赖的头文件是 #include <numeric>,而不是<algorithm>

而当我写如下的测试代码的时候,vs2017社区版能正常计算结果,但总给我警告:xxxx2017communityvc oolsmsvc14.16.27023include umeric(26): warning C4244: “=”: 从“double”转换到“_Ty”,可能丢失数据
感觉不应该有警告才对呢:

#include <string>
namespace AccumulateOpNS
{
  std::string LinkStr(const std::string &init, double dv)
  {
    return "";
    //return init + "_" + std::to_string(dv);
  }
}

void funcRun_accumulate3()
{
  std::vector<double> vecTest{ 0.3,0.3,0.9,0.9 };
  std::string begStr("beg");
  std::cout << std::accumulate(vecTest.begin(), vecTest.end(), begStr, AccumulateOpNS::LinkStr) << std::endl;
  // beg_0.300000_0.300000_0.900000_0.900000
}
 
 

原文地址:https://www.cnblogs.com/xiarl/p/3683133.html