Std::vector: vec.data() или & vec [0]
Когда вы хотите получить доступ к std::vector как массив C, вы можете выбрать по крайней мере четыре разных способа, как вы можете видеть в этом примере:
#include <iostream>
#include <vector>
using namespace std;
int main() {
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(42);
vec.push_back(24024);
{
int* arr = vec.data();
cout << arr << endl; /* output: 0x9bca028 */
cout << arr[3] << endl; /* output : 24024 */
}
{
int* arr = &vec.front();
cout << arr << endl; /* output: 0x9bca028 */
cout << arr[3] << endl; /* output : 24024 */
}
{
int* arr = &vec[0];
cout << arr << endl; /* output: 0x9bca028 */
cout << arr[3] << endl; /* output : 24024 */
}
{
int* arr = &vec.at(0);
cout << arr << endl; /* output: 0x9bca028 */
cout << arr[3] << endl; /* output : 24024 */
}
}
В большинстве случаев я нашел &vec[0]
. Я думаю, что он наименее изящный, поэтому... почему он наиболее часто используется? Является ли более эффективным или более совместимым? Я не могу найти много документации о data()
.
Ответы
Ответ 1
data()
является совершенно новым для С++ 11, поэтому вы не видите его так часто. Идея использования &vec.front()
мне даже и не приходила в голову, вероятно, потому, что я использую operator[]
чаще, чем front()
(почти никогда). Я думаю, это то же самое для других людей.
Ответ 2
Если вы используете С++ 11, то использовать data()
определенно предпочтительнее. В частности, если вектор пуст, то использование любого из двух других вариантов дает поведение undefined! Если вы не используете С++ 11, и вектор может быть пустым, тогда обязательно проверьте это условие.
Ответ 3
Использование & vec [0] является наиболее распространенным, хотя, я согласен, выглядит немного странно. Одно нужно помнить о будущем. Если ваш вектор является вектором объектов, класс которых перегружает оператор &(), поймите, что это вызовет странное поведение, если вы вызываете & vec [0].
Это не получит начальный адрес первого элемента во внутреннем смежном массиве объектов, он вернет все, что вернет vec [0].operator &(). Большинство, если не все время, это не адрес, который вы ищете (ручная волна джедая).
Хорошим примером этого является ATL CComPtr. Он перегружает оператор &(), поэтому сохранение его в векторе может быть проблематичным. Чтобы обойти это, ATL имеет класс шаблонов CAdapt, который может быть использован для скрытия оператора &() на CComPtr
Ответ 4
До С++ 11 std::array
Я бы сказал, что std::vector
был наиболее распространенным контейнером, который будет использоваться вместо массива C-стиля. Оператор []
обычно подразумевает постоянный доступ времени (это то, о чем говорит std::vector
), и поэтому большинство кодеров обычно выбирают этот стиль, чтобы отображать доступ и поведение, подобные массиву.
Ответ 5
data() уже некоторое время является частью std::string
, поэтому вы можете прочитать об этом. Я обнаружил, что реализация data() в std::vector
аналогична. Я иногда использую data() для обработки std::string
как массив необработанных байтов.