В некотором роде напрашивается вопрос, почему? Вы можете получить доступ к вектору в виде массива. Что делает массив, чего не делает вектор?
Майкл Дорган
96
@Michael Типичный вариант использования, который у меня есть, заключается в использовании вектора в моем собственном коде и необходимости вызова сторонней функции, которая принимает массив
Майкл Мрозек
7
Терминология сбрасывается с толку. Указатель не является массивом. Хотим ли мы указатель на первый элемент массива или массив?
GManNickG
7
Абсолютно реальный вопрос - довольно простой, легко интерпретируемый. пожалуйста, откройте заново.
ДБЛИСС
10
«В некотором роде напрашивается вопрос, почему?» - Во-первых, неправильное использование этой фразы. Во-вторых, ясно, почему.
Джим Балтер
Ответы:
534
Для этого есть довольно простой трюк, поскольку спецификация теперь гарантирует, что векторы хранят свои элементы непрерывно:
@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. Элементы вектора являются смежными.
В противном случае вам просто нужно скопировать каждый элемент:
Примечание: используйте 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()]это недействительно. Использование вектора вместо нового - хорошая идея, но весь вопрос в том, как преобразовать вектор в массив.
Это гарантированно сработает по стандарту, однако есть некоторые предостережения: в частности, позаботьтесь о том, чтобы использовать только thearrayтогда, когда это thevectorнаходится в рамках.
Если у вас есть функция, то вам , вероятно , нужно это: foo(&array[0], array.size());. Если вам удалось попасть в ситуацию, когда вам нужен массив, вам нужно провести рефакторинг, векторы - это в основном расширенные массивы, вы всегда должны их использовать.
Ответы:
Для этого есть довольно простой трюк, поскольку спецификация теперь гарантирует, что векторы хранят свои элементы непрерывно:
источник
double*
что указывает на те же данные. Этот ответ работает именно для этого случаяstd::vector<double> v; double* a = v.data();
Зачем? Вам необходимо уточнить: нужен ли вам указатель на первый элемент массива или массив?
Если вы вызываете функцию API, которая ожидает первого, вы можете сделать
do_something(&v[0], v.size())
, гдеv
есть векторdouble
s. Элементы вектора являются смежными.В противном случае вам просто нужно скопировать каждый элемент:
Убедитесь, что не только thar
arr
достаточно велик, но иarr
заполнен, или у вас есть неинициализированные значения.источник
size()
функции,std:vector
которую вам нужно использоватьnew
илиmalloc
для этого. Как уже было отмечено (вами),double arr[v.size()]
это недействительно. Использование вектора вместо нового - хорошая идея, но весь вопрос в том, как преобразовать вектор в массив.Для C ++ 11 ,
vector.data()
сделаем свое дело.источник
Это гарантированно сработает по стандарту, однако есть некоторые предостережения: в частности, позаботьтесь о том, чтобы использовать только
thearray
тогда, когда этоthevector
находится в рамках.источник
empty()
, иначе это вызовет страшный UB.Векторы эффективно представляют собой массивы под кожей. Если у вас есть функция:
Вы можете назвать это так:
Вам никогда не нужно преобразовывать вектор в фактический экземпляр массива.
источник
f( &v[0] );
для вашей последней строкиЧто касается
std::vector<int> vec
, чтобы получитьint*
, вы можете использовать два метода:int * arr = & vec [0];
int * arr = vec.data ();
Если вы хотите преобразовать
T
вектор любого типа вT* array
, просто замените приведенное вышеint
наT
.Я покажу вам, почему вышеупомянутые две работы, для хорошего понимания?
std::vector
это динамический массив по существу.Основной элемент данных, как показано ниже:
Это
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_источник
Мы можем сделать это с помощью метода data (). C ++ 11 предоставляет этот метод.
Фрагмент кода
источник
источник
Если у вас есть функция, то вам , вероятно , нужно это:
foo(&array[0], array.size());
. Если вам удалось попасть в ситуацию, когда вам нужен массив, вам нужно провести рефакторинг, векторы - это в основном расширенные массивы, вы всегда должны их использовать.источник
Вы можете сделать что-то подобное
источник