Hungry Mind , Blog about everything in IT - C#, Java, C++, .NET, Windows, WinAPI, ...

Показаны сообщения с ярлыком best practice. Показать все сообщения
Показаны сообщения с ярлыком best practice. Показать все сообщения

Use ATL string convertion properly

В ATL 7 появилось новое семейство СX2Y макросов для конвертации строк из текущей кодовой страницы в UNICODE и обратно. И я заметил, что их часто используют абсолютно неправильно! Например:

const std::wstring some = L"Some";
AfxMessageBox(CW2T(some.c_str()));

Код выглядит, как не содержащий ошибок. Но на самом деле это не так. Взгляните на макрос CW2T когда определен _UNICODE (atlconv.h):

#ifdef _UNICODE

    #define CW2T CW2W

А теперь самое интересное:

template< int t_nBufferLength = 128 >
class CW2WEX
{
public:
    CW2WEX( _In_opt_ LPCWSTR psz ) throw(...) :
        m_psz( m_szBuffer )
    {
        Init( psz );
    }
    CW2WEX( _In_opt_ LPCWSTR psz, UINT nCodePage ) throw(...) :
        m_psz( m_szBuffer )
    {
        (void)nCodePage;  // Code page doesn't matter

        Init( psz );
    }
    ~CW2WEX() throw()
    {
        AtlConvFreeMemory(m_psz,m_szBuffer,t_nBufferLength);
    }

    operator LPWSTR() const throw()
    {
        return( m_psz );
    }

private:
    void Init( _In_opt_ LPCWSTR psz ) throw(...)
    {
        if (psz == NULL)
        {
            m_psz = NULL;
            return;
        }
        int nLength = lstrlenW( psz )+1;
        AtlConvAllocMemory(&m_psz,nLength,m_szBuffer,t_nBufferLength);
        ATLASSUME(m_psz != NULL);
        Checked::memcpy_s( m_psz, nLength*sizeof( wchar_t ), psz, nLength*sizeof( wchar_t ));
    }

public:
    LPWSTR m_psz;
    wchar_t m_szBuffer[t_nBufferLength];

private:
    CW2WEX( const CW2WEX& ) throw();
    CW2WEX& operator=( const CW2WEX& ) throw();
};
typedef CW2WEX<> CW2W;

CW2WEX выполняет копирование строки даже в случае, когда этого можно избежать, как в примере выше!

Используйте макросы CX2CY чтобы избежать лишнего копирования строк:

#ifdef _UNICODE

    #define CW2T CW2W
    #define CW2TEX CW2WEX
    #define CW2CT CW2CW
    #define CW2CTEX CW2CWEX
    #define CT2W CW2W
    #define CT2WEX CW2WEX
    #define CT2CW CW2CW
    #define CT2CWEX CW2CWEX

template< int t_nBufferLength = 128 >
class CW2CWEX
{
public:
    CW2CWEX( _In_ LPCWSTR psz ) throw(...) :
        m_psz( psz )
    {
    }
    CW2CWEX( _In_ LPCWSTR psz, UINT nCodePage ) throw(...) :
        m_psz( psz )
    {
        (void)nCodePage;
    }
    ~CW2CWEX() throw()
    {
    }

    operator LPCWSTR() const throw()
    {
        return( m_psz );
    }

public:
    LPCWSTR m_psz;

private:
    CW2CWEX( const CW2CWEX& ) throw();
    CW2CWEX& operator=( const CW2CWEX& ) throw();
};
typedef CW2CWEX<> CW2CW;

Copyright 2007-2011 Chabster