Доступ к оператору [] из указателя
Если я определю указатель на объект, который определяет []
оператор, есть ли прямой способ доступа к этому оператору из указателя?
Например, в следующем коде я могу получить прямой доступ Vec
функции-члены (такие как empty()
) с помощью указателя ->
оператор, но если я хочу получить доступ к []
Оператор мне нужно сначала получить ссылку на объект, а затем вызвать оператор.
#include <vector>
int main(int argc, char *argv[])
{
std::vector<int> Vec(1,1);
std::vector<int>* VecPtr = &Vec;
if(!VecPtr->empty()) // this is fine
return (*VecPtr)[0]; // is there some sort of ->[] operator I could use?
return 0;
}
Я вполне могу ошибаться, но похоже, что (*VecPtr).empty()
менее эффективно, чем делать VecPtr->empty()
, Вот почему я искал альтернативу (*VecPtr)[]
,
7 ответов
Вы можете сделать любое из следующего:
#include <vector>
int main () {
std::vector<int> v(1,1);
std::vector<int>* p = &v;
p->operator[](0);
(*p)[0];
p[0][0];
}
Кстати, в частном случае std::vector
Вы также можете выбрать: p->at(0)
хотя он имеет немного другое значение.
return VecPtr->operator[](0);
... сделает свое дело. Но на самом деле, (*VecPtr)[0]
форма выглядит лучше, не так ли?
Есть еще один способ, вы можете использовать ссылку на объект:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v = {7};
vector<int> *p = &v;
// Reference to the vector
vector<int> &r = *p;
cout << (*p)[0] << '\n'; // Prints 7
cout << r[0] << '\n'; // Prints 7
return 0;
}
Сюда, r
такой же как v
и вы можете заменить все вхождения (*p)
от r
,
Предостережение: это будет работать только в том случае, если вы не измените указатель (т.е. измените объект, на который он указывает).
Учтите следующее:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v = {7};
vector<int> *p = &v;
// Reference to the vector
vector<int> &r = *p;
cout << (*p)[0] << '\n'; // Prints 7
cout << r[0] << '\n'; // Prints 7
// Caveat: When you change p, r is still the old *p (i.e. v)
vector<int> u = {3};
p = &u; // Doesn't change who r references
//r = u; // Wrong, see below why
cout << (*p)[0] << '\n'; // Prints 3
cout << r[0] << '\n'; // Prints 7
return 0;
}
r = u;
неверно, потому что вы не можете изменить ссылки: это изменит вектор, на который ссылаютсяr
(v
) вместо ссылки на другой вектор (u
). Итак, опять же, это работает, только если указатель не изменится при использовании ссылки.
В примерах C++11 нужен только из-заvector<int> ... = {...};
(*VecPtr)[0]
совершенно нормально, но вы можете использовать at
Функция, если вы хотите:
VecPtr->at(0);
Имейте в виду, что это (в отличие от operator[]
) брошу std::out_of_range
исключение, если индекс не находится в диапазоне.
Вы можете использовать его как VecPrt->operator [] ( 0 )
, но я не уверен, что вы найдете это менее неясным.
Стоит отметить, что в C++11 std::vector имеет функцию-член "data", которая возвращает указатель на базовый массив (как константной, так и неконстантной версий), что позволяет написать следующее:
VecPtr->data()[0];
Это может быть альтернативой
VecPtr->at(0);
Это приводит к небольшим накладным расходам времени выполнения, но, что более важно, его использование подразумевает, что вы не проверяете индекс на достоверность перед его вызовом, что не так в вашем конкретном примере.
Смотрите std:: vector:: data для более подробной информации.
Люди советуют вам использовать ->at(0)
из-за проверки диапазона. Но вот мой совет (с другой точки зрения):
НИКОГДА не используйте ->at(0)
! Это действительно медленнее. Вы бы пожертвовали производительностью только потому, что вы достаточно ленивы, чтобы не проверять дальность самостоятельно? Если это так, вы не должны программировать на C++.
Я думаю (*VecPtr)[0]
в порядке