Доступ к оператору [] из указателя

Если я определю указатель на объект, который определяет [] оператор, есть ли прямой способ доступа к этому оператору из указателя?

Например, в следующем коде я могу получить прямой доступ 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] в порядке

Другие вопросы по тегам