Boost logo

Boost Users :

Subject: [Boost-users] Extra copy construction in boost::as_literal
From: Sergey Nozhenko (snhere_at_[hidden])
Date: 2011-02-12 21:49:57


Hi,

Looking at the code generated by MSVC++ 2008 from a call to
boost::algorithms::replace_all with std::wstrings as arguments I came across
this remarkable piece of work:

=== cut ===
; 109 : return range_detail::make_range( r, range_detail::is_char_ptr(r) );

        xor eax, eax
        push -1
        mov WORD PTR $T115029[esp+44], ax
        push eax
        mov eax, edi
        lea ecx, DWORD PTR $T115029[esp+44]
        mov DWORD PTR $T115029[esp+68], 7
        mov DWORD PTR $T115029[esp+64], 0
        call ?assign@?$basic_string@_WU?$char_traits@_W_at_std@@V?$allocator...
        cmp DWORD PTR $T115029[esp+60], 8
        jb SHORT $LN52_at_as_literal
        mov ecx, DWORD PTR $T115029[esp+40]
        push ecx
        call ??3_at_YAXPAX@Z ; operator delete
                ...
=== cut ===

Checked it with g++ -O2 and found that it produced something similar:

=== cut ===
 109:.../boost/boost/range\as_literal.hpp ****
     return range_detail::make_range( r, range_detail::is_char_ptr(r) );
        leal 168(%esp), %ebx
        movl %ebx, 4(%esp)
        leal 164(%esp), %eax
        movl %eax, (%esp)
        call __ZNSbIwSt11char_traitsIwESaIwEEC1ERKS2_
        movl 168(%esp), %eax
        movl %eax, 44(%esp)
        movl -12(%eax), %edx
        movl %edx, 52(%esp)
        movl 164(%esp), %eax
        leal -12(%eax), %ebx
        cmpl $__ZNSbIwSt11char_traits..._Rep20_S_empty_rep_storageE, %ebx
        jne L412
L284:
                ...
L412:
        movl 8(%ebx), %eax
        leal -1(%eax), %edx
        movl %edx, 8(%ebx)
        testl %eax, %eax
        jg L284
        leal 188(%esp), %eax
        movl %eax, 4(%esp)
        movl %ebx, (%esp)
        call __ZNSbIwSt11char_traitsIwESaIwEE4_Rep10_M_destroyERKS1_
        jmp L284
=== cut ===

I.e., even with the optimization turned on, a call to "inline" function

        template< class T >
        inline long is_char_ptr( T /* r */ )
        {
            return 0L;
        }

in boost/range/as_literal.hpp causes the creation of a temporary copy of every
string passed to boost::as_literal. :( I believe it would have been better to
define that function as

        template< class T >
        inline long is_char_ptr(const T& /* r */ )
        {
            return 0L;
        }

Serge


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net