//for_each()调用三次析构函数
仿函数(functor),就是使一个类的使用看上去象一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。
有些功能的的代码,会在不同的成员函数中用到,想复用这些代码。
1)公共的函数,可以,这是一个解决方法,不过函数用到的一些变量,就可能成为公共的全局变量,再说为了复用这么一片代码,就要单立出一个函数,也不是很好维护。
2)仿函数,写一个简单类,除了那些维护一个类的成员函数外,就只是实现一个operator(),在类实例化时,就将要用的,非参数的元素传入类中。
C++中,我们通过在一个类中重载括号运算符的方法使用一个函数对象而不是一个普通函数。
#include "stdafx.h"
#include <iostream>
#include <algorithm>
using namespace std;
class A {
public:
void operator()(const int &x) {
cout << x << endl;
}
};
int main()
{
int arr[]={0,1,2,3,4};
for_each(arr,arr+5,A());
return 0;
}
上述代码实际上就是调用A()类中重载了的()的运算符来实现仿函数。当然也会调用默认的构造函数和析构函数。
#include "stdafx.h"
#include <iostream>
#include <algorithm>
using namespace std;
class A {
public:
A(){cout<<"A()"<<endl;}
void operator()(const int &x) {
cout << x << endl;
}
~A(){cout<<"~A()"<<endl;}
};
int main()
{
int arr[]={0,1,2,3,4};
for_each(arr,arr+5,A());
return 0;
}
/*
A()
0
1
2
3
4
~A()
~A()
~A()
请按任意键继续. . .
*/
结果我们看到了,调用了一次我们定义的构造函数,而调用了三次析构函数。
第一次:初始化
第二次:for_each参数值传递发生一次拷贝构造
第三次:for_each返回第三个参数,又一次拷贝构造
问题在于 for_each() 函数中,如果我们没有定义拷贝构造函数,for_each()函数在传值的过程中会发生拷贝构造。
所以,在我们定义拷贝自己的拷贝构造后,就可以解释了
#include "stdafx.h"
#include <iostream>
#include <algorithm>
using namespace std;
class A {
public:
A() { cout << "A()" << endl; }
A(const A &o) { cout << "A(const A &o)" << endl; }
void operator()(const int &x) {
cout << x << endl;
}
~A() { cout << "~A()" << endl; }
};
int main()
{
int arr[] = { 0,1,2,3,4 };
for_each(arr, arr + 5, A());
return 0;
}
/*
A()
0
1
2
3
4
A(const A &o)
~A()
~A()
请按任意键继续. . .
*/
系统调用了一次我们自己定义的拷贝构造函数。这里出现了2次析构函数,实际上我猜测是在for_each()函数中,如果在函数内定义初始化for_each()的第三个函数,则函数会直接将初始化的值传入,优化了一次。就类似与:
#include "stdafx.h"
#include <iostream>
#include <algorithm>
using namespace std;
class A {
public:
A() { cout << "A()" << endl; }
A(int x):i(x) { cout << "A(int x): "<<i << endl; }
~A() { cout << "~A()" << endl; }
int i;
};
int main()
{
int arr[] = { 0,1,2,3,4 };
A a; //调用构造函数A()
a = 6; //临时调用构造函数A(int x),完成赋值后立刻析构
return 0;
}
通过直接在定义的时候就初始化优化了一个构造函数:
#include "stdafx.h"
#include <iostream>
#include <algorithm>
using namespace std;
class A {
public:
A() { cout << "A()" << endl; }
A(int x):i(x) { cout << "A(int x): "<<i << endl; }
~A() { cout << "~A()" << endl; }
int i;
};
int main()
{
int arr[] = { 0,1,2,3,4 };
A a = 6; //调用构造函数A(int x)
return 0;
}
所以,为何定义拷贝构造函数后,析构函数减少了一个,原因就是被优化了,我们可以还原:
#include "stdafx.h"
#include <iostream>
#include <algorithm>
using namespace std;
class A {
public:
A() { cout << "A()" << endl; }
A(const A &o) { cout << "A(const A &o)" << endl; }
void operator()(const int &x) {
cout << x << endl;
}
~A() { cout << "~A()" << endl; }
};
int main()
{
int arr[] = { 0,1,2,3,4 };
A t = A(); //初始化
for_each(arr, arr + 5, t); /*for_each参数值传递发生一次拷贝构造;for_each返回第三个参数,又一次拷贝构造*/
return 0;
}
这里给出for_each()的函数原型:
template<typename InputIterator, typename Function>
Function for_each(InputIterator beg, InputIterator end, Function f) {
while(beg != end)
f(*beg++);
}