Обработать 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, я хочу ссылаться на существующие данные как на один.
Ответы
Ответ 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).