C++, Инициализирующий структуру с массивом как участник

Отредактированный снова, потому что первоначально не было ясно, что я пытаюсь инициализировать массивы во время компиляции, не во время выполнения...


У меня есть следующий уменьшенный тестовый сценарий:

typedef struct TestStruct
{
    int length;
    int values[];
};

TestStruct t = {3, {0, 1, 2}};
TestStruct t2 = {4, {0, 1, 2, 3}};

int main()
{
    return(0);
}

Это работает с Visual C++, но не компилирует с g ++ в соответствии с Linux. Кто-либо может помочь мне сделать этот определенный вид инициализатора портативным?

Дополнительные детали: фактическая структура, с которой я работаю, имеет несколько других международных значений, и массив может расположиться в длине от однократного въезда до более чем 1 800 записей.

Править: Я думаю (но не уверено), что это не проблема VLA. Для разъяснения я пытаюсь заставить компилятор делать работу для меня во время компиляции. Длина массива во времени выполнения является постоянной. Извинения, если я неправ; я - прежде всего, c#/Perl/Ruby программист, который застревает, поддерживая это приложение прежней версии...

Любая справка очень ценится.Спасибо!

25
задан Drew Shafer 16 April 2010 в 04:25
поделиться

2 ответа

В c ++ нет такого же гибкого элемента массива, как последний элемент, как у c99. Вы должны использовать std :: vector , если вы не знаете, сколько элементов, или вы должны указать, сколько, если вы знаете.

РЕДАКТИРОВАТЬ: В своей редакции вы сказали, что массив является константой времени выполнения, поэтому укажите размер, и он должен работать нормально. g ++ не имеет проблем со следующим кодом:

struct TestStruct { // note typedef is not needed */
    int length;
    int values[3]; // specified the size
};

TestStruct t = {3, {0, 1, 2}};

int main() {
    // main implicitly returns 0 if none specified
}

РЕДАКТИРОВАТЬ: для ответа на ваш комментарий вы можете использовать такие шаблоны, как этот:

template <int N>
struct TestStruct {
    int length;
    int values[N];
};

TestStruct<3> t3 = {3, {0, 1, 2}};
TestStruct<2> t2 = {2, {0, 1}};

int main() {}

Единственная проблема заключается в том, что нет простого способа поместить и t2, и t3 в контейнер (например, список / вектор / стек / очередь / и т. д., потому что они имеют разные размеры. Если вы этого хотите, вы должны использовать std :: vector .Кроме того, если вы это делаете, то нет необходимости хранить размер (он связан с типом). Так что вы можете сделать это вместо этого:

template <int N>
struct TestStruct {
    static const int length = N;
    int values[N];
};

TestStruct<3> t3 = {{0, 1, 2}};
TestStruct<2> t2 = {{0, 1}};

int main() {}

Но опять же, вы не можете легко объединить t2 и t3 в «коллекцию».

РЕДАКТИРОВАТЬ: В общем, похоже, что вам (если вы не храните больше данных, чем просто некоторые числа и размер) вообще не нужна структура, и вы не можете просто использовать простой старый вектор.

typedef std::vector<int> TestStruct;


int t2_init[] = { 0, 1, 2 };
TestStruct t3(t3_init, t3_init + 3);

int t2_init[] = { 0, 1 };
TestStruct t2(t2_init, t2_init + 2);

int main() {}

Это позволит вам иметь в коллекции как t2, так и t3. К сожалению, std :: vector (пока) не имеет синтаксиса инициализатора стиля массива, поэтому я использовал ярлык. Но достаточно просто написать функцию для удобного заполнения векторов.

РЕДАКТИРОВАТЬ: Итак, вам не нужна коллекция, но вам нужно передать ее функции, вы можете использовать для этого шаблоны, чтобы сохранить безопасность типов!

template <int N>
struct TestStruct {
    static const int length = N;
    int values[N];
};

TestStruct<3> t3 = {{0, 1, 2}};
TestStruct<2> t2 = {{0, 1}};

template <int N>
void func(const TestStruct<N> &ts) { /* you could make it non-const if you need it to modify the ts */
    for(int i = 0; i < N; ++i) { /* we could also use ts.length instead of N here */
        std::cout << ts.values[i] << std::endl;
    }
}

// this will work too...
template <class T>
void func2(const T &ts) { 
    for(int i = 0; i < ts.length; ++i) {
        std::cout << ts.values[i] << std::endl;
    }
}

int main() {
    func(t2);
    func(t3);
    func2(t2);
}
29
ответ дан 28 November 2019 в 21:34
поделиться

VLA поддерживается только в C99. C ++ этого не поддерживает. Начиная с http://gcc.gnu.org/c99status.html , gcc теперь поддерживает VLA.

0
ответ дан 28 November 2019 в 21:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: