Translation of the article: blog.linderdaum.com/2014/07/03/smart-pointers-passed-by-const-reference
const size_t NUM_CALLS = 10000000; double GetSeconds() { return ( double )clock() / CLOCKS_PER_SEC; } void PrintElapsedTime( double ElapsedTime ) { printf( "%fs/Mcalls\n", float( ElapsedTime / double( NUM_CALLS / 10000000 ) ) ); }
class iIntrusiveCounter { public: iIntrusiveCounter():FRefCounter(0) {}; virtual ~iIntrusiveCounter() {} void IncRefCount() { FRefCounter++; } void DecRefCount() { if ( --FRefCounter == 0 ) { delete this; } } private: std::atomic<int> FRefCounter; };
template <class T> class clPtr { public: clPtr(): FObject( 0 ) {} clPtr( const clPtr& Ptr ): FObject( Ptr.FObject ) { FObject->IncRefCount(); } clPtr( T* const Object ): FObject( Object ) { FObject->IncRefCount(); } ~clPtr() { FObject->DecRefCount(); } clPtr& operator = ( const clPtr& Ptr ) { T* Temp = FObject; FObject = Ptr.FObject; Ptr.FObject->IncRefCount(); Temp->DecRefCount(); return *this; } inline T* operator -> () const { return FObject; } private: T* FObject; };
class clTestObject: public iIntrusiveCounter { public: clTestObject():FPayload(32167) {} // - void Do() { FPayload++; } private: int FPayload; };
void ProcessByValue( clPtr<clTestObject> O ) { O->Do(); } void ProcessByConstRef( const clPtr<clTestObject>& O ) { O->Do(); } int main() { clPtr<clTestObject> Obj = new clTestObject; for ( size_t j = 0; j != 3; j++ ) { double StartTime = GetSeconds(); for ( size_t i = 0; i != NUM_CALLS; i++ ) { ProcessByValue( Obj ); } PrintElapsedTime( GetSeconds() - StartTime ); } for ( size_t j = 0; j != 3; j++ ) { double StartTime = GetSeconds(); for ( size_t i = 0; i != NUM_CALLS; i++ ) { ProcessByConstRef( Obj ); } PrintElapsedTime( GetSeconds() - StartTime ); } return 0; }
gcc -O0 main.cpp -lstdc++ -std=c++11
L25: leal -60(%ebp), %eax leal -64(%ebp), %edx movl %edx, (%esp) movl %eax, %ecx call __ZN5clPtrI12clTestObjectEC1ERKS1_ // subl $4, %esp leal -60(%ebp), %eax movl %eax, (%esp) call __Z14ProcessByValue5clPtrI12clTestObjectE leal -60(%ebp), %eax movl %eax, %ecx call __ZN5clPtrI12clTestObjectED1Ev // addl $1, -32(%ebp) L24: cmpl $10000000, -32(%ebp) jne L25
L29: leal -64(%ebp), %eax movl %eax, (%esp) call __Z17ProcessByConstRefRK5clPtrI12clTestObjectE // addl $1, -40(%ebp) L28: cmpl $10000000, -40(%ebp) jne L29
gcc -O3 main.cpp -lstdc++ -std=c++11
L25: call _clock movl %eax, 36(%esp) fildl 36(%esp) movl $10000000, 36(%esp) fdivs LC0 fstpl 24(%esp) .p2align 4,,10 L24: movl 32(%esp), %eax lock addl $1, (%eax) // IncRefCount()... movl 40(%esp), %ecx addl $1, 8(%ecx) // ProcessByValue() Do() 2 lock subl $1, (%eax) // DecRefCount(). . jne L23 movl (%ecx), %eax call *4(%eax) L23: subl $1, 36(%esp) jne L24 call _clock
call _clock movl %eax, 36(%esp) movl 40(%esp), %eax addl $10000000, 8(%eax) // , , call _clock movl %eax, 32(%esp) movl $20, 4(%esp) fildl 32(%esp) movl $LC2, (%esp) movl $1, 48(%esp) flds LC0 fdivr %st, %st(1) fildl 36(%esp) fdivp %st, %st(1) fsubrp %st, %st(1) fstpl 8(%esp) call _printf
Source: https://habr.com/ru/post/228687/
All Articles