【侯捷-SL体系结构内核分析-算法】
目录:
accumulate
for_each
replace, replace_if, replace_copy
accumulate 的源码如下。
template<class _InIt,
class _Ty,
class _Fn>
_NODISCARD inline _Ty accumulate(const _InIt _First, const _InIt _Last, _Ty _Val, _Fn _Reduce_op)
{ // return noncommutative and nonassociative reduction of _Val and all in [_First, _Last), using _Reduce_op
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
for (; _UFirst != _ULast; ++_UFirst)
{
_Val = _Reduce_op(_Val, *_UFirst);
}
return (_Val);
}
template<class _InIt,
class _Ty>
_NODISCARD inline _Ty accumulate(const _InIt _First, const _InIt _Last, _Ty _Val)
{ // return noncommutative and nonassociative reduction of _Val and all in [_First, _Last)
return (_STD accumulate(_First, _Last, _Val, plus<>()));
}
_Val = _Reduce_op(_Val, *_UFirst);
int myFunc(int x, int y)
{
return x + 2 * y;
}
struct myClass
{
int operator()(int x, int y)
{
return x + 3 * y;
}
}myObj;
void test_accumulate()
{
int nInit = 100;
int data[3] = { 10, 20, 30 };
int result = std::accumulate(data, data + 3, nInit);
// 100 + 10 + 20 + 30 = 160
std::cout << result << endl;
result = std::accumulate(data, data + 3, nInit, myFunc);
// 100 + 2 * 10 + 2 * 20 + 2 * 30 = 220
std::cout << result << endl;
result = std::accumulate(data, data + 3, nInit, myObj);
// 100 + 3 * 10 + 3 * 20 + 3 * 30 = 280
std::cout << result << endl;
}
void test_accumulate()
{
int nInit = 0;
float data[3] = { 10.3, 20.4, 30.5 };
float result = std::accumulate(data, data + 3, nInit);
std::cout << result << endl;
}
正确的输出应该是 61.2,但是实际输出为 60,这是为什么呢?
可以往前看看 accumulate 的源代码,可以看到,计算结果的类型会根据传入初值参数类型进行判断,与容器数值类型并没有关系,由于这里传入初值 nInit 为整形,所以每次累加时都会转换成整型类型,最后输出60。如果将 nInit 改为和容器数据类型相同浮点类型,就可以得出正确结果。
template<class _InIt,
class _Fn> inline
_Fn for_each(_InIt _First, _InIt _Last, _Fn _Func)
{ // perform function for each element [_First, _Last)
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
for (; _UFirst != _ULast; ++_UFirst)
{
_Func(*_UFirst);
}
return (_Func);
}
vector<int> myVec = vector<int>{ 0, 1, 2, 3,4 };
for (auto i : myVec)
{
cout << i << " ";
}
template<class _FwdIt,
class _Ty> inline
void replace(const _FwdIt _First, const _FwdIt _Last, const _Ty& _Oldval, const _Ty& _Newval)
{ // replace each matching _Oldval with _Newval
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
for (; _UFirst != _ULast; ++_UFirst)
{
if (*_UFirst == _Oldval)
{
*_UFirst = _Newval;
}
}
}
template<class _FwdIt,
class _Pr,
class _Ty> inline
void replace_if(const _FwdIt _First, const _FwdIt _Last, _Pr _Pred, const _Ty& _Val)
{ // replace each satisfying _Pred with _Val
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
for (; _UFirst != _ULast; ++_UFirst)
{
if (_Pred(*_UFirst))
{
*_UFirst = _Val;
}
}
}
template<class _InIt,
class _OutIt,
class _Ty> inline
_OutIt replace_copy(_InIt _First, _InIt _Last,
_OutIt _Dest, const _Ty& _Oldval, const _Ty& _Newval)
{ // copy replacing each matching _Oldval with _Newval
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast));
for (; _UFirst != _ULast; ++_UFirst, (void)++_UDest)
{
if (*_UFirst == _Oldval)
{
*_UDest = _Newval;
}
else
{
*_UDest = *_UFirst;
}
}
_Seek_wrapped(_Dest, _UDest);
return (_Dest);
}