2015-11-11 5 views
-1

У меня есть массив данных в массиве C++/CLI, который я могу передать на нативную функцию, используя pin_ptr<T>, без проблем. Теперь, однако, мне нужно передать массив на функцию C++/STL, которая ожидает контейнер, такой как std::array или std::vector.std :: array или std :: vector from pointer

Простой способ сделать это (что я сделал первым) - это скопировать элемент по элементу.

Второй способ - позвонить std::copy(), см. Ответ на этот вопрос: convert System::array to std::vector.

Однако я хочу пропустить весь шаг копирования и вместо этого использовать указатель. Видя, как std::array требует аргумента шаблона для определения его длины, я не могу создать его во время выполнения (но, пожалуйста, исправьте меня, если я ошибаюсь). Есть ли способ создать вектор или другой тип контейнера STL без ненужного копирования данных?

+0

Это может сработать, но assumming, что C++/CLI имеет [System :: Массив] (https://msdn.microsoft.com/en-us/library/system.array (v = vs.110) .aspx? f = 255 & MSPPError = -2147217396 & cs-save-lang = 1 & cs-lang = cpp # code-snippet-1), это может быть не так чисто. Кроме того, у вас есть только базовые типы? Нет строк или 'ref class', которые необходимо преобразовать? Любой из этих случаев также исключает прохождение указателей. – crashmstr

+0

Я имею дело только с структурами, которые содержат такие вещи, как int, char, float ... Так что полу-базовые типы, если хотите. –

ответ

1

Нет, это невозможно обойтись без копирования, а не со стандартными контейнерами.

Если вы все еще в порядке с копированием, вы должны посмотреть на std::vector constructor, потому что я думаю, что самый простой способ - это сделать, например.

std::vector<T>(your_pointer, your_pointer + number_of_elements) 

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


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

См https://gist.github.com/pileon/c21cfba496e6c352dd81

Пример программы с использованием его:

#include <iostream> 
#include "pointer_container.h" 

int main() 
{ 
    int a[20]; 
    std::iota(a, a + 20, 0); // Initialize array 

    { 
     std::cout << "From array : "; 
     for (const auto item : a) 
     { 
      std::cout << item << ' '; 
     } 
     std::cout << '\n'; 
    } 

    pointer_container<int> c(a, 20); 
    { 
     std::cout << "From container: "; 
     for (const auto item : c) 
     { 
      std::cout << item << ' '; 
     } 
     std::cout << '\n'; 
    } 
} 

Ожидаемый выход из программы:

 
From array : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
From container: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
+0

Сегодня не мой день - я должен был сначала прочитать ваш ответ ... –

+0

Да, мне было интересно, будет ли сложно написать что-то обычное, напоминающее контейнер STL. Я думаю, что это на самом деле очень полезно! –

0

С станд :: массив просто обертка вы можете бросить регулярный массив к указателю на std :: array. Конечно, это нельзя использовать для других контейнеров.

#include <array> 
#include <iostream> 

void test(std::array<int, 10>* pia) 
{ 
    std::cout << (*pia)[0] << std::endl; 
} 


int main() 
{ 
    int ix[10]{ 0 }; 
    test((std::array<int, 10> *) ix); 
} 
+0

Да, я подумал об этом. Проблема в том, что я заранее не знаю, как долго мой массив будет (т. Е. Ваш второй аргумент шаблона). Я ценю ваши усилия, хотя! –

Смежные вопросы