实现一个高效C++委托类(多分派)

博客展示了一个高效C++委托类(多分派)的实现代码。定义了测试结构体和多个测试函数,创建了Functor模板类,可添加不同参数的函数并调用。在main函数中进行了性能测试,调用委托类的函数,体现了该委托类在多分派场景下的应用。
乱七八糟,有空再整理。

1、暂命名为Functor,因为没考虑返回值的情况,这在多分派委托处理中,算是个麻烦事,以后类名可能改为Delegate。
2、根据i_like_cpp翻译的技术文章《成员函数指针与高性能的C++委托》提供的思路做成的,不过原文所提到的FastDelegate实现太复杂,所以自己做了一个,可能不完善,不过初步测试基本功能达到了,而且实现要简单一些。
3、原本vector遍历用的是迭代器,不过测试发现速度比用下标访问慢10倍以上,改成下标访问,测试表明速度已经和直接调用差不多。实际测试结果非常相近,用GetTickCount获取的结果,有时是直接调用要快一些,有时是使用Functor要快一些,当然Functor不可能比直接调用还快。
4、实现没有写完,先写了3个版本做测试用,成型以后会实现更多版本(支持更多参数)。下午一时心血来潮写成的,离成型还很远,不过从效率测试来看值得做。


None.gif#include <vector> 
None.gif#include 
<functional> 
None.gif#include 
<iostream> 
None.gif#include 
<string> 
None.gif#include 
<windows.h> 
None.gif
using namespace std; 
None.gif
None.gif
struct Test 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    
int n; 
ExpandedSubBlockStart.gifContractedSubBlock.gif    Test () : n(
3dot.gif{} 
InBlock.gif    
void test0() 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        
//cout << "Test::test0: " << n << endl; 
ExpandedSubBlockEnd.gif
    }
 
InBlock.gif
InBlock.gif    
void test1(int i) 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        
//cout << "Test::test1: " << i << endl; 
ExpandedSubBlockEnd.gif
    }
 
InBlock.gif
InBlock.gif    
void test2(const string& a, int b) 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        
//cout << "Test::test2: " << a << "|" << b << endl; 
ExpandedSubBlockEnd.gif
    }
 
ExpandedBlockEnd.gif}

None.gif
None.gif
void test0 () 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    
//cout << "test0" << endl; 
ExpandedBlockEnd.gif
}
 
None.gif
None.gif
void test1 (int i) 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    
//cout << "test1: " << i << endl; 
ExpandedBlockEnd.gif
}
 
None.gif
None.gif
void test2(const string& a, int b) 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    
//cout << "test2: " << a << "|" << b << endl; 
ExpandedBlockEnd.gif
}
 
None.gif
ExpandedBlockStart.gifContractedBlock.gif
struct NullType dot.gif{}
None.gif
None.giftemplate 
<typename R, typename A=NullType, typename B=NullType, typename C=NullType, 
None.giftypename D
=NullType, typename E=NullType, typename F=NullType, typename G=NullType, 
None.giftypename H
=NullType, typename I=NullType, typename J=NullType, typename K=NullType, 
None.giftypename L
=NullType, typename M=NullType, typename N=NullType, typename O=NullType> 
None.gif
class Functor 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
ExpandedBlockEnd.gif}

None.gif
None.giftemplate 
<typename R> 
None.gif
struct Functor <R> 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    vector 
<pair<void*void*> > _handlers; 
InBlock.gif    typedef R(
*F)(); 
InBlock.gif
InBlock.gif    
void add (F f) 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        _handlers.push_back (make_pair ((
void*)0, (void*)f)); 
ExpandedSubBlockEnd.gif    }
 
InBlock.gif
InBlock.gif    template 
<typename T> 
InBlock.gif    
void add (const pair<T*, typename R(T::*)()>& f) 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        typedef R(T::
*P)(); 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
struct Pointer dot.gif{P p;}
ExpandedSubBlockStart.gifContractedSubBlock.gif        Pointer ptr 
= dot.gif{f.second}
InBlock.gif        _handlers.push_back (make_pair ((
void*)f.first, *(void**)&ptr)); 
ExpandedSubBlockEnd.gif    }
 
InBlock.gif
InBlock.gif    
void call () 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        
for (size_t i=0; i<_handlers.size (); i++
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            
void* p = _handlers[i].first; 
InBlock.gif            
if (p) // member function 
ExpandedSubBlockStart.gifContractedSubBlock.gif
            dot.gif
InBlock.gif                
void* mem_fun = _handlers[i].second; 
ExpandedSubBlockStart.gifContractedSubBlock.gif                __asm
dot.gif
InBlock.gif                    mov ecx, p 
InBlock.gif                    call mem_fun 
ExpandedSubBlockEnd.gif                }
 
ExpandedSubBlockEnd.gif            }
 
InBlock.gif            
else 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                (
*(F)_handlers[i].second)(); 
ExpandedSubBlockEnd.gif            }
 
ExpandedSubBlockEnd.gif        }
 
ExpandedSubBlockEnd.gif    }
 
ExpandedBlockEnd.gif}

None.gif
None.giftemplate 
<typename R, typename A> 
None.gif
struct Functor <R, A> 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    vector 
<pair<void*void*> > _handlers; 
InBlock.gif    typedef R(
*F)(A); 
InBlock.gif
InBlock.gif    
void add (F f) 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        _handlers.push_back (make_pair ((
void*)0, (void*)f)); 
ExpandedSubBlockEnd.gif    }
 
InBlock.gif
InBlock.gif    template 
<typename T> 
InBlock.gif    
void add (const pair<T*, typename R(T::*)(A)>& f) 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        typedef R(T::
*P)(A); 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
struct Pointer dot.gif{P p;}
ExpandedSubBlockStart.gifContractedSubBlock.gif        Pointer ptr 
= dot.gif{f.second}
InBlock.gif        _handlers.push_back (make_pair ((
void*)f.first, *(void**)&ptr)); 
ExpandedSubBlockEnd.gif    }
 
InBlock.gif
InBlock.gif    
void call (A a) 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        
for (size_t i=0; i<_handlers.size (); i++
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            
void* p = _handlers[i].first; 
InBlock.gif            
if (p) // member function 
ExpandedSubBlockStart.gifContractedSubBlock.gif
            dot.gif
InBlock.gif                
void* mem_fun = _handlers[i].second; 
ExpandedSubBlockStart.gifContractedSubBlock.gif                __asm
dot.gif
InBlock.gif                    push a 
InBlock.gif                    mov ecx, p 
InBlock.gif                    call mem_fun 
ExpandedSubBlockEnd.gif                }
 
ExpandedSubBlockEnd.gif            }
 
InBlock.gif            
else 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                (
*(F)_handlers[i].second)(a); 
ExpandedSubBlockEnd.gif            }
 
ExpandedSubBlockEnd.gif        }
 
ExpandedSubBlockEnd.gif    }
 
ExpandedBlockEnd.gif}

None.gif
None.giftemplate 
<typename R, typename A, typename B> 
None.gif
struct Functor <R, A, B> 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    vector 
<pair<void*void*> > _handlers; 
InBlock.gif    typedef R(
*F)(A, B); 
InBlock.gif
InBlock.gif    
void add (F f) 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        _handlers.push_back (make_pair ((
void*)0, (void*)f)); 
ExpandedSubBlockEnd.gif    }
 
InBlock.gif
InBlock.gif    template 
<typename T> 
InBlock.gif    
void add (const pair<T*, typename R(T::*)(A, B)>& f) 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        typedef R(T::
*P)(A, B); 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
struct Pointer dot.gif{P p;}
ExpandedSubBlockStart.gifContractedSubBlock.gif        Pointer ptr 
= dot.gif{f.second}
InBlock.gif        _handlers.push_back (make_pair ((
void*)f.first, *(void**)&ptr)); 
ExpandedSubBlockEnd.gif    }
 
InBlock.gif
InBlock.gif    
void call (A a, B b) 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        
for (size_t i=0; i<_handlers.size (); i++
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            
void* p = _handlers[i].first; 
InBlock.gif            
if (p) // member function 
ExpandedSubBlockStart.gifContractedSubBlock.gif
            dot.gif
InBlock.gif                
void* mem_fun = _handlers[i].second; 
ExpandedSubBlockStart.gifContractedSubBlock.gif                __asm
dot.gif
InBlock.gif                    push b 
InBlock.gif                    push a 
InBlock.gif                    mov ecx, p 
InBlock.gif                    call mem_fun 
ExpandedSubBlockEnd.gif                }
 
ExpandedSubBlockEnd.gif            }
 
InBlock.gif            
else 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                (
*(F)_handlers[i].second)(a, b); 
ExpandedSubBlockEnd.gif            }
 
ExpandedSubBlockEnd.gif        }
 
ExpandedSubBlockEnd.gif    }
 
ExpandedBlockEnd.gif}

None.gif
None.gif
None.gif
int main(int argc, char* argv[]) 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    Test t; 
InBlock.gif    DWORD cur 
= GetTickCount (); 
InBlock.gif    
for (int i=0; i<10000000; i++
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        t.test0(); 
ExpandedSubBlockEnd.gif    }
 
InBlock.gif    cout 
<< (GetTickCount() - cur) << endl; 
InBlock.gif
InBlock.gif    Functor 
<void> f; 
InBlock.gif    f.add (make_pair(
&t, &Test::test0)); 
InBlock.gif    f.add (test0); 
InBlock.gif    cur 
= GetTickCount (); 
InBlock.gif    
for (int i=0; i<1000000; i++
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        f.call(); 
ExpandedSubBlockEnd.gif    }
 
InBlock.gif    cout 
<< (GetTickCount() - cur) << endl; 
InBlock.gif
InBlock.gif    f.call ();
InBlock.gif
InBlock.gif    Functor
<voidint> f1; 
InBlock.gif    f1.add (test1); 
InBlock.gif    f1.add (make_pair (
&t, &Test::test1)); 
InBlock.gif    f1.add (test1); 
InBlock.gif    f1.add (test1); 
InBlock.gif    f1.call (
93); 
InBlock.gif
InBlock.gif    Functor
<voidconst string&int> f2; 
InBlock.gif    f2.add (test2); 
InBlock.gif    f2.add (make_pair (
&t, &Test::test2)); 
InBlock.gif    f2.add (test2); 
InBlock.gif    f2.add (test2); 
InBlock.gif    f2.call (
string("hello"), 5); 
InBlock.gif    
return 0
ExpandedBlockEnd.gif}
 

转载于:https://www.cnblogs.com/cpunion/archive/2005/07/22/198288.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值