Например:
InitEmployee()
{
vector<Employee> employeeList = {
Employee("Clark Kent",0),
Employee("Bruce Wayne",1),
...
Employee("Hal Jordan",65535)
}
}
Я не могу сделать запрос из файла или базы данных, так как эта программа должна быть в одном исполняемом файле, поэтому все постоянные данные должны быть жестко запрограммированы. Я на самом деле использую мультисимметричный Boost для быстрого поиска по имени и идентификатору, но для простоты я использовал здесь вектор в качестве примера. Проблема в том, что у меня не может быть столько (2 ^ 16) константных данных в одной функции без переполнения стека. Есть ли лучшие способы инициализировать этот список без разделения функции?
Я использую VC12. Спасибо!
Обновить
Смотрите выбранный ответ. Как уже упоминали другие, использование static заставит их идти на данные, а не на стек. Вот чем я закончил:
InitEmployee()
{
static Employee employeeList[] = {
{"Clark Kent",0},
{"Bruce Wayne",1},
...
{"Hal Jordan",65535}
}
vector<Employee*> employeeVec;
int count = sizeof(employeeList) / sizeof(Employee);
for (int i = 0; i < count; i++)
{
employeeVec.emplace(&employeeList[i]);
}
}
Дело в том, что класс Employee использовал строковый класс, а не c-string, поэтому я не хотел, чтобы две его копии были в памяти. Таким образом, у меня останется только дополнительная память для указателей, которой еще много, но я считаю, что это лучший вариант! Также работает с multi_index_container! Спасибо
Используйте статический массив для хранения данных инициализации.
InitEmployee()
{
static char const* const names[] = {
"Clark Kent",
"Bruce Wayne",
...
"Hal Jordan"};
size_t const n = sizeof(names) / sizeof(*names);
vector<Employee> employeeList;
employeeList.reserve(n);
for (size_t i=0; i<n; ++i)
employeeList.emplace_back(names[i],i);
...
}
Вы уверены, что слишком много строковых литералов приведет к переполнению стека?
Даже если они это сделают, вы можете попытаться поместить их в глобальную область:
const char *data = R"(
Clark Kent,0
Bruce Wayne,1
...
Hal Jordan,65535)"
/* ... */
int main()
{
/* ... */
}
Если он прекрасно скомпилируется с огромным строковым литералом, вы можете даже попытаться использовать необработанные данные из какого-либо файла БД вместо списка.
Поскольку вы говорите, что используете VC 12, и у вас есть один исполняемый файл (и нет файла данных), поместите жестко закодированные данные в ресурсы, а не в программный код.
Подходящим ресурсом будет тип RCDATA.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa381039(v=vs.85).aspx
Есть два варианта, которые приходят на ум. Первое зависит от версии Visual Studio. Используете ли вы Visual Studio 2012 или версию 12.0 (смущает, что VS2012 на самом деле 11.0). Если вы используете 2013 (то есть 12.0), то у вас есть возможность использовать списки инициализаторов, которые являются новыми в C ++ 11 (например, см. Часто задаваемые вопросы)
vector<Employee> employeeList = {
{"Clark Kent",0},
{"Bruce Wayne",1},
...
{"Hal Jordan",65535}
};
Списки инициализатора полагаются на семантику перемещения значения C ++ 11, чтобы гарантировать, что в результате вы получите только одну копию данных в приложении.
Другим вариантом может быть использование boost::assign
(см. документы), что означает, что вы можете использовать тот же тип синтаксиса, но выполнять распределение динамически:
#include <boost/assign/std/vector.hpp> // for 'operator+=()'
using namespace boost::assign; // bring operator+= into scope
vector<Employee> employeeList;
employeeList += Employee("Clark Kent", 0),
Employee("Bruce Wayne", 1), ...