Как преобразовать вектор в массив

352

Как я могу преобразовать std::vector<double>в double array[]?

ganuke
источник
9
В некотором роде напрашивается вопрос, почему? Вы можете получить доступ к вектору в виде массива. Что делает массив, чего не делает вектор?
Майкл Дорган
96
@Michael Типичный вариант использования, который у меня есть, заключается в использовании вектора в моем собственном коде и необходимости вызова сторонней функции, которая принимает массив
Майкл Мрозек
7
Терминология сбрасывается с толку. Указатель не является массивом. Хотим ли мы указатель на первый элемент массива или массив?
GManNickG
7
Абсолютно реальный вопрос - довольно простой, легко интерпретируемый. пожалуйста, откройте заново.
ДБЛИСС
10
«В некотором роде напрашивается вопрос, почему?» - Во-первых, неправильное использование этой фразы. Во-вторых, ясно, почему.
Джим Балтер

Ответы:

534

Для этого есть довольно простой трюк, поскольку спецификация теперь гарантирует, что векторы хранят свои элементы непрерывно:

std::vector<double> v;
double* a = &v[0];
Майкл Мрозек
источник
29
@ganuke Вы не копируете, вы создаете указатель, который указывает на фактический массив, который вектор использует внутри. Если вы хотите скопировать ответ GMan объясняет, как
Майкл Мрозек
4
@ganuke: Что такое "массив"? Вам необходимо предоставить больше информации. Что за картина?
GManNickG
6
@ganuke Вы не хотите, вам просто нужно, double*что указывает на те же данные. Этот ответ работает именно для этого случая
Майкл Мрозек
6
@guneykayim Вектор владеет этой памятью, вы не должны ее освобождать
Майкл Мрозек
23
std::vector<double> v; double* a = v.data();
sinoTrinity
148

Зачем? Вам необходимо уточнить: нужен ли вам указатель на первый элемент массива или массив?

Если вы вызываете функцию API, которая ожидает первого, вы можете сделать do_something(&v[0], v.size()), где vесть вектор doubles. Элементы вектора являются смежными.

В противном случае вам просто нужно скопировать каждый элемент:

double arr[100];
std::copy(v.begin(), v.end(), arr);

Убедитесь, что не только thar arrдостаточно велик, но и arrзаполнен, или у вас есть неинициализированные значения.

GManNickG
источник
15
Примечание: используйте v.size (), чтобы получить количество элементов для нового массива: double arr [v.size ()];
rbaleksandar
7
@rbaleksandar: Массивы не могут иметь размер непостоянного выражения.
GManNickG
@GManNickG: это работает, но я думаю, что здесь есть некоторое недопонимание. Представьте себе следующее: у вас есть класс с набором указателей различных типов, которые должны указывать на массивы, которые неизвестны в момент определения класса и которые впоследствии создаются путем сброса различных векторов и использования их параметра размера определить, сколько места должно быть использовано. Другой пример: простая функция void arrayTest (unsigned int arrSize), которая создает в ней массив (short arr [arrSize];), используя для этого размер функции-параметра.
rbaleksandar
1
@rbaleksandar Нет недоразумений; в C ++ 11 и более ранних версиях размеры массивов должны быть целочисленными константными выражениями. Ваш пример функции широко используется для VLA в C, но поддерживается только (нестандартным) расширением в C ++. Это может прийти к C ++ 14, хотя: stackoverflow.com/a/17318040/87234 . Но на данный момент это просто не стандартный вариант.
GManNickG
1
@GManNickG Я думаю, что @Jet говорит, что если вы хотите преобразовать вектор в массив, и вы намерены изменить размер массива с помощью size()функции, std:vectorкоторую вам нужно использовать newили mallocдля этого. Как уже было отмечено (вами), double arr[v.size()]это недействительно. Использование вектора вместо нового - хорошая идея, но весь вопрос в том, как преобразовать вектор в массив.
RyanP
17
vector<double> thevector;
//...
double *thearray = &thevector[0];

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

user168715
источник
4
... и убедитесь, что вектора нет empty(), иначе это вызовет страшный UB.
ВОО
13

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

void f( double a[]);

Вы можете назвать это так:

vector <double> v;
v.push_back( 1.23 )
f( &v[0] );

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


источник
1
Я думаю, что вы имели в виду f( &v[0] );для вашей последней строки
Майкл Мрозек
10

Что касается std::vector<int> vec, чтобы получить int*, вы можете использовать два метода:

  1. int * arr = & vec [0];

  2. int * arr = vec.data ();

Если вы хотите преобразовать Tвектор любого типа в T* array, просто замените приведенное выше intна T.

Я покажу вам, почему вышеупомянутые две работы, для хорошего понимания?

std::vector это динамический массив по существу.

Основной элемент данных, как показано ниже:

template <class T, class Alloc = allocator<T>>
class vector{
    public:
        typedef T          value_type;
        typedef T*         iterator;
        typedef T*         pointer;
        //.......
    private:
        pointer start_;
        pointer finish_;
        pointer end_of_storage_;

    public:
        vector():start_(0), finish_(0), end_of_storage_(0){}
    //......
}

Это range (start_, end_of_storage_)вся память массива, которую выделяет вектор;

Это range(start_, finish_)вся память массива, используемая вектором;

range(finish_, end_of_storage_)Является резервной памяти массива.

Например, что касается вектора vec. который имеет указатель {9, 9, 1, 2, 3, 4}, может выглядеть следующим образом.

введите описание изображения здесь

So &vec[0]= start_ (address.) (Start_ эквивалентно int * заголовку массива)

В c++11 в data()функции члена просто вернуть start_

pointer data()
{ 
     return start_; //(equivalent to `value_type*`, array head)
}
Jayhello
источник
2

Мы можем сделать это с помощью метода data (). C ++ 11 предоставляет этот метод.

Фрагмент кода

#include<bits/stdc++.h>
using namespace std;


int main()
{
  ios::sync_with_stdio(false);

  vector<int>v = {7, 8, 9, 10, 11};
  int *arr = v.data();

  for(int i=0; i<v.size(); i++)
  {
    cout<<arr[i]<<" ";
  }

  return 0;
}
rashedcs
источник
2
std::vector<double> vec;
double* arr = vec.data();
Тоби
источник
1

Если у вас есть функция, то вам , вероятно , нужно это: foo(&array[0], array.size());. Если вам удалось попасть в ситуацию, когда вам нужен массив, вам нужно провести рефакторинг, векторы - это в основном расширенные массивы, вы всегда должны их использовать.


источник
-1

Вы можете сделать что-то подобное

vector <int> id;
vector <double> v;

if(id.size() > 0)
{
    for(int i = 0; i < id.size(); i++)
    {
        for(int j = 0; j < id.size(); j++)
        {
            double x = v[i][j];
            cout << x << endl;
        }
    }
}
Шакти Виньеш
источник
v [i] [j]; для 2d массива
Шакти Вигнеш