использовать векторный вместо динамически выделяемого массива wchar

#c #stdvector

#c #stdvector

Вопрос:

На днях меня отчитали (в stackoverflow!) за то, что я не использовал vector вместо динамически выделяемого массива wchar.

Итак, я рассмотрел возможность использования этого метода манипулирования строками, поскольку это кажется хорошей идеей для предотвращения возможных утечек памяти.

Я пришел к выводу, что, если я не использую класс vector template неправильно, использование vector намного менее гибко, чем использование массива, выделенного из кучи, и старого доброго memcpy.

 #include <shlobj.h>
HRESULT ModifyTheme()
{
using namespace std;

vector <WCHAR>  sOutput;
vector <WCHAR>  sPath;      
vector <WCHAR>  sThemesLocation;
vector <WCHAR>  sThemeName; 

const WCHAR sThemesPath []  = _T("\Microsoft\Windows\Themes");
const WCHAR sFileName []    = _T("\darkblue.theme");

sOutput.resize(MAX_PATH);
sPath.resize( MAX_PATH );   
sThemesLocation.resize( MAX_PATH );
sThemeName.resize( MAX_PATH );

// Get appdatalocal folder
SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, amp;sPath[0] );

// copy consts to vectors   
memcpy( amp;sThemesLocation[0],    sThemesPath,    sizeof(sThemesPath) );
memcpy( amp;sThemeName[0],         sFileName,      sizeof(sFileName) );    

// append themes path amp; filename
sOutput.insert( sOutput.begin(), sPath.begin(), sPath.end() );
sOutput.insert( sOutput.end()-1, sThemesLocation.begin(), sThemesLocation.end() );
sOutput.insert( sOutput.end()-1, sThemeName.begin(), sThemeName.end() );    

wcout << amp;sThemeName[0] << endl;
wcout << amp;sThemesLocation[0] << endl;
wcout << amp;sPath[0] << endl;
wcout << amp;sOutput[0] << endl;

return S_OK;
}
  

Я бы ожидал, что вектор sOutput будет содержать конкатенацию всех строк. Вместо этого он содержит только первую вставленную строку.

Также, я думаю, я помню, что слышал, что, хотя невозможно присвоить значения вектора в списке инициализаторов, это может быть особенностью c 0x. Правильно ли это — и есть ли какой-либо способ (на данный момент) выполнить следующее:

 vector<wchar> sBleh = { _T("bleh") };
  

Наконец, для того, чего я хочу достичь с помощью простой процедуры, описанной выше, было бы лучше использовать динамически выделяемый массив или мне следует придерживаться кажущегося негибким вектора wchar?

Комментарии:

1. Вы могли бы попробовать std::wstring .

2. wcout << amp;sThemeName[0] << endl; выводит содержимое вектора только до тех пор, '' первый .

Ответ №1:

Если вы используете, std::vector<WCHAR> вам, вероятно, следует использовать std::wstring , поскольку это также контейнер WCHAR элементов.

Следующие ссылки могут помочь вам:
std::wstring (определение типа std::basic_string<WCHAR> )
std::basic_string

Ответ №2:

Используйте лучший инструмент для этой работы. В некоторых ситуациях требуется использовать статические массивы, а в некоторых — динамические массивы. Когда ситуация требует динамического массива, используйте вместо него vector.

Марк Ингрэм прав, что вы могли бы использовать wstring, но только если wchar_t имеет тот же размер, что и WCHAR.

Что-то вроде этого лучше для того, что вы хотите (обратите внимание, я не запускал приведенное ниже через компилятор, потому что существует слишком много конструкций, специфичных для Microsoft.):

 WCHAR sPath[MAX_PATH]; // doesn't need to be a dynamic array, so don't bother with a vector.
SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, amp;sPath[0] );

const WCHAR sThemesPath[] = _T("\Microsoft\Windows\Themes"); // doesn't need to be a dynamic array, so don't bother with a vector.
const WCHAR sFileName[] = _T("\darkblue.theme"); // doesn't need to be a dynamic array, so don't bother with a vector.
vector<WCHAR> sOutput; // this needs to be dynamic so use a vector.

// wcslen should probably be replaced with an MS specific call that gets the length of a WCHAR string
copy(sPath, sPath   wcslen(sPath), back_inserter(sOutput));
copy(sThemesPath, sThemesPath   wcslen(sThemesPath), back_inserter(sOutput));
copy(sFlieName, sFileName   wcslen(sFileName), back_inserter(sOutput));