Подтвердить что ты не робот

Обработать C cstyle массив как std:: array

Существует ли безопасный и стандартный способ обработки массива стиля C как std:: array без копирования данных в новый std:: array?

Это явно не компилируется, но это эффект, который мне бы хотелось (мое реальное использование сложнее, но этот короткий образец должен показать, что я хотел бы сделать). Я предполагаю, что reinterpret_cast "работает", но, вероятно, небезопасен?

#include <array>

int main()
{
    int data[] = {1, 2, 3, 4, 5};

    // This next line is the important one, treating an existing array as a std::array
    std::array<int, 5>& a = data;
}

Похоже, что это должно быть возможно, поскольку данные должны храниться одинаково.

edit: Чтобы быть ясным, я не хочу очищать новый std:: array, я хочу ссылаться на существующие данные как на один.

4b9b3361

Ответ 1

Вы не можете этого сделать. std::array является агрегатом и содержит собственный блок данных (в отличие от указателя на блок данных, который можно легко переназначить). Поэтому нет способа избежать копирования всех элементов. В С++ 11 это особенно важно, потому что данные массива не могут быть перемещены, поэтому нет эффективной функции std::swap, например.

Ответ 2

Как обсуждалось в этом сообщении Является std:: array < T, S > гарантированно быть POD, если T является POD?

std::array<int, N> - это POD и, таким образом, стандартная компоновка. Насколько я понимаю стандартные требования к макету, это означает, что указатель на объект идентичен указателю на первый элемент. Поскольку std:: array не имеет частных/защищенных членов (согласно http://en.cppreference.com/w/cpp/container/array), это должно совпадать с первым элементом в обернутом массиве, Таким образом, что-то вроде

reinterpret_cast< std::array<int, 5>* >( &data )

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

Отношения Claas

Ответ 3

Вы можете использовать reinterpret_cast, однако обратите внимание, что это уродливый грязный взломать, и вы не должны делать что-то подобное в своем реальном коде выпуска:

std::array<int, 5> &a = reinterpret_cast<std::array<int, 5>&>(data);

Проблемы могут возникнуть, если изменится внутренняя реализация std:: array (например, некоторые дополнительные поля будут добавлены в отладочную версию STL для выполнения некоторых проверок времени выполнения). Затем этот код начнет сбой без каких-либо информационных сообщений (поскольку он основан на неявном предположении, что объект std:: array и массив C имеют одинаковый макет памяти).

Если вы решите пойти на уродливый грязный взлом, тем не менее, по крайней мере добавить проверку размера компиляции:

    C_ASSERT(sizeof(a) == sizeof(data));

Это приведет к ошибке, если размер std:: array < > перестанет соответствовать размеру вашего массива C (из-за некоторых изменений в реализации STL).