Указатель указателя разницы для элемента доступа
Если у меня есть в С++ указатель на вектор:
vector<int>* vecPtr;
И я хотел бы получить доступ к элементу вектора, тогда я могу сделать это, разрезая вектор:
int a = (*vecPtr)[i];
но будет ли это разыменование фактически создать копию моего вектора в стеке? скажем, что вектор хранит 10000 ints, будет ли разыменован vecPtr 10000 ints скопирован?
Спасибо!
Ответы
Ответ 1
10000 int
не будет скопировано. Разбор разговора очень дешев.
Чтобы сделать это, вы можете переписать
int a = (*vecPtr)[i];
как
vector<int>& vecRef = *vecPtr; // vector is not copied here
int a = vecRef[i];
Кроме того, если вы боитесь, что все данные, хранящиеся в vector
, будут расположены в стеке, и вместо vector<int>
используйте vector<int>*
вместо vector<int>
: это не так.
На самом деле в стеке используется только фиксированный объем памяти (около 16-20 байтов в зависимости от реализации), независимо от количества элементов, хранящихся в vector
.
Сам vector
выделяет память и сохраняет элементы в куче.
Ответ 2
Нет, ничего не будет скопировано; разыменование просто говорит С++, что вы хотите вызывать оператор [] на векторе, а не на вашем указателе, vecPtr
. Если вы не разыменовали, С++ попытается найти оператор [], определенный в типе std::vector<int>*
.
Это может стать очень запутанным, поскольку operator[]
определяется для всех типов указателей, но это равнозначно смещению указателя, как если бы он указывал на массив vector<int>
. Если бы вы действительно выделили только один вектор, то для любого индекса, отличного от 0
, выражение оценивается ссылкой на мусор, поэтому вы получите либо segfault, либо то, чего вы не ожидали.
В общем, доступ к векторам через указатель - боль, а синтаксис (*vecPtr)[index]
неудобен (но лучше, чем vecPtr->operator[](index)
). Вместо этого вы можете использовать:
vecPtr->at(index)
Это фактически проверяет диапазоны, в отличие от operator[]
, поэтому, если вы не хотите платить цену за проверку того, находится ли индекс в границах, вы застряли с (*vecPtr)[]
.