2016-06-19 5 views
2

У меня естьИнициализировать многомерный вектор C++ с многомерным массивом?

float viewerMatrix[4][4] = 
    { 
     {0.99962944, -0.023989394, -0.012864082, -0.032067116}, 
     {0.02354476, 0.9991557, -0.033667795, -0.0060634422}, 
     {0.013660891, 0.033352438, 0.99935031, 0.047027141}, 
     { 0, 0, 0, 1} 
    }; 

Я хотел сохранить это в классе, и там будет много больше из них, так что я думал, поместив его в vector является хорошей идеей. Мне нужно преобразовать этот массив в vector<vector<float>>, а затем после этого push_back в член класса, который имеет тип vector< vector<vector<float>> >.

Итак, могу ли я инициализировать vector<vector<float>> с помощью этого массива? То, что я пытался

vector<vector<float>> floatVector (viewerMatrix);

не работает.

error: invalid conversion from ‘float (*)[4]’ to ‘std::vector<std::vector<float> >::size_type {aka long unsigned int}’ [-fpermissive] 
+0

Зачем вам это нужно, чтобы инициализировать его из промежуточного массива? –

+0

Это результат другого метода, который я не контролирую. Он выводит 2-мерный массив, и я хотел сохранить этот результат в своем классе. – 5argon

+0

Ну, вам нужно скопировать в цикле, тогда нет прямого преобразования. –

ответ

1

Проблема с этим - это макет памяти: двухмерный массив C [4] [4] расположен в памяти, так как 16 (4 * 4) плавают подобно массиву float [16]. Но вектор вектора, расположенный по-другому: он более похож на динамический массив float **, и каждый элемент типа float * выделяется отдельно. Это означает, что вы не можете просто передать указатель на свой двумерный массив и быть хорошим. Но вы можете использовать алгоритмы STL.

Прежде всего std::vector и простой массив C, оба являются совместимыми с STL. Предположим, вам нужно инициализировать std::vector с одним массивным массивом C. Я должен написать что-то вроде этого:

float testArray[4]={0.99962944, -0.023989394, -0.012864082, -0.032067116}; 
vector<float> testVector(testArray,testArray+4); 

Он построит новый вектор и перебирать от testArray (это указатель) на testArray+4 (это указатель тоже) и push_back каждый элемент в testVector. Таким образом, самый простой способ добиться того, что вы хотите:

vector<vector<float>> floatVector{ 
    {viewerMatrix[0],viewerMatrix[0]+4}, 
    {viewerMatrix[1],viewerMatrix[1]+4}, 
    {viewerMatrix[2],viewerMatrix[2]+4}, 
    {viewerMatrix[3],viewerMatrix[3]+4}, 
}; 

Конечно 4 значения в размерах может быть изменен, так что лучше, чтобы создать функцию, которая принимает двумерный массив любого числа элементов и возвращает std::vector<std::vector<float>>. Например:

template<size_t M,size_t N> 
std::vector<std::vector<float>> initVectorWithTwoDimArray(float (&ar)[M][N]){ 
    std::vector<std::vector<float>> res; 
    res.reserve(M); 
    for(auto i=0;i<M;++i){ 
     res.emplace_back(ar[i],ar[i]+N); 
    } 
    return std::move(res); 
} 

float viewerMatrix[4][4] = 
{ 
    {0.99962944, -0.023989394, -0.012864082, -0.032067116}, 
    {0.02354476, 0.9991557, -0.033667795, -0.0060634422}, 
    {0.013660891, 0.033352438, 0.99935031, 0.047027141}, 
    { 0, 0, 0, 1} 
}; 

auto floatVector=initVectorWithTwoDimArray(viewerMatrix); 

Теперь floatVector является std::vector из std::vector<float> содержал ваши две тусклый массив.

Редактировать

Если вам понравилась эта функция может быть воссозданы с массивом любого типа не только float:

template<class T,size_t M,size_t N> 
std::vector<std::vector<T>> initVectorWithTwoDimArray(T (&ar)[M][N]){ 
    std::vector<std::vector<T>> res; 
    res.reserve(M); 
    for(auto i=0;i<M;++i){ 
     res.emplace_back(ar[i],ar[i]+N); 
    } 
    return std::move(res); 
} 

Эта версия будет работать для любого типа массивов: int, double, AnyYourClass и т. Д.То же самое:

float viewerMatrix[4][4] = 
{ 
    {0.99962944, -0.023989394, -0.012864082, -0.032067116}, 
    {0.02354476, 0.9991557, -0.033667795, -0.0060634422}, 
    {0.013660891, 0.033352438, 0.99935031, 0.047027141}, 
    { 0, 0, 0, 1} 
}; 

auto floatVector=initVectorWithTwoDimArray(viewerMatrix); 
1

У вас не может быть vector массива. Если вам действительно нужно сохранить вывод в vector, я бы сказал, сделать что-то вроде

class Matrix 
{ 
float m[4][4]; 
}; 

, а затем скопировать ваши вещи снова и вставьте его в vector.

+1

Почему бы не 'std :: array , 4> m;'? –

+0

Я просто предпочитаю массивы c-style в этом случае. Из того, что я знаю, не должно быть никаких штрафов за производительность при использовании контейнера. –

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