关于函子的问题

Question about functors

本文关键字:问题 于函      更新时间:2023-10-16
正确的

答案是D,但我感到困惑的是,dunno类中的添加操作究竟是什么时候发生的?数字是如何添加的?

请考虑以下部分C++代码:

#include <vector>
#include <iostream>
using namespace std;
template<class Iter, class Formatter>
void mystery(Iter front, Iter end, Formatter doSomething)
{
    while (front != end)
    {
        doSomething(*front, *end):
        front++; end--;
    }
}
template <class T> class dunno
{
public:
    void operator()(T & a, T & b)
    {
        a = a + b;
    }
}
int main()
{
    vector<int> v; ... // insert an odd number of elements into the vector
    vector<int>::iterator it1 - v.begin();
    vector<int>::iterator it2 - v.end();
    it2--;
    dunno<int> d;
    mystery<vector<int>::iterator, dunno<int> >(itl, it2, d);
    for (int i = 0; i < v.size(); i++) cout << v[i] << endl;
    return 0;
}

如果您假设所有迭代器都是双向且非常量,那么以下哪项陈述是正确的?

(a) 由于神秘参数列表中的类型不匹配,此代码无法编译。

(b) 由于模板实例化中的语法错误,此代码无法编译。

(c) 如果向量按该顺序由整数 1、2、3、4、5、6、7 组成,第一项在左边,则输出为 1、2、3、4、5、6、7。(即代码 Dods 不会更改向量。

(d) 如果向量按该顺序由整数 1、2、3、4、5、6、7 组成,第一项在左边,则输出为 8、8、8、4、5、6、7。

(e) 这些选项都没有描述此代码的行为。

当我们调用 mystery() 时

   | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
     ^                       ^
     |                       |
   front                    end

front   is from v.begin();
end     is from v.end() (note: this is one past the end)
        followed by a -- operator that moves it back one.

现在我们开始循环:

while(front != end)

因此,这将在它们不相等时循环。 在循环内,两者同时移动:

front++; end--;

所以每次迭代将如下所示:

Iteration 1:
   | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
     ^                       ^
     |                       |
   front                    end
Iteration 2:
   | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
         ^               ^
         |               |
       front            end
Iteration 3:
   | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
             ^       ^
             |       |
           front    end
The loop is not entered.
   | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
                 ^
                 |
           front   end

因此,每次通过循环时,我们还执行以下操作:

doSomething(*front, *end):

现在doSomething是一个格式化程序(模板参数)类型的对象,它解码为dunno该方法void operator()(T & a, T & b)在替换模板参数T后我们得到void operator()(int & a, int & b)

所以这行:

doSomething(*front, *end):

是句法糖,用于:

doSomething.operator()(*front, *end):

这具有调用此运算符的效果,将取消引用的迭代器作为参数传递。这实际上与以下相同:

Iteration 1:
    v[0]    = v[0] + v[6]; // Note v[0] == 1 v[6] == 7 etc.
  //v[0]    =  1   +   7;
Iteration 2:
    v[1]    = v[1] + v[5];
  //v[1]    =  2   +   6
Iteration 3:
    v[2]    = v[2] + v[4];
  //v[2]    =  3   +   5

因此,如果您的起始数组是:

1 2 3 4 5 6 7

最终结果是:

8 8 8 4 5 6 7

dunno functor的operator()在每次调用doSomething时都会被神秘地调用。由于参数是通过引用传递的,因此作为"a"传入的值每次都会更新。所以你最终得到的是一个包含 1+7、2+6、3+5、4、5、6、7 的列表。因为当迭代器在值 4 处相遇时,神秘内部的循环就结束了。

dunno 实例 d 作为参数传递给 mystery,然后由形式参数 doSomething 指定,其运算符 () 在 while 循环中调用。