Ваш первый пример размещает массив в стеке, что возможно только потому, что компилятор знает размер (поскольку все строки имеют фиксированную длину и указываются во время объявления).
Когда вы разделяете объявление и инициализацию, вашу компилятора нет возможности узнать, сколько памяти выделить в стеке, поэтому вам нужно изменить тип на указатель (который имеет фиксированный размер, независимо от того, на что он указывает):
static const char** desc;
изатем используйте new
, чтобы выделить достаточно памяти для массива:
desc = new const char*[3]{ "apple", "banana", "orange" };
Однако это означает, что теперь вы также должны delete[]
массив, на который указывает desc
, иначе вы получите утечку памяти.
Намного лучше было бы использовать современные типы контейнеров, такие как std::vector
и std::string
:
static std::vector<std::string> desc;
, а затем
desc.push_back("apple");
desc.push_back("banana");
desc.push_back("orange");
Эти классы заботятся обо всехнеприятное управление памятью для вас под капотом.
Другая альтернатива, если вы действительно хотите необработанный массив и не хотите полагаться на new[]
и delete[]
, это объявить фиксированныйразмер массива с достаточным пространством для ваших строк, например:
static const char desc[3][128];
и последующее копирование строковых значений в этот блок памяти:
std::strcpy(desc[0], "apple");
std::strcpy(desc[1], "banana");
std::strcpy(desc[2], "orange");
Однако я действительно не рекомендую делатьЭто связано с тем, что вы рискуете ошибками в долгосрочной перспективе при добавлении или удалении строк, изменении их длины и т. д.