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;