Доступ к оператору [] из указателя - PullRequest
31 голосов
/ 13 декабря 2011

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

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

36 голосов
/ 13 декабря 2011

Вы можете сделать любое из следующего:

#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), хотя оно имеет немного другое значение.

8 голосов
/ 13 декабря 2011
return VecPtr->operator[](0);

... сделает свое дело. Но действительно, форма (*VecPtr)[0] выглядит лучше, не так ли?

3 голосов
/ 13 декабря 2011

Вы можете использовать его как VecPrt->operator [] ( 0 ), но я не уверен, что вы найдете его менее темным.

2 голосов
/ 20 сентября 2017

Есть еще один способ, вы можете использовать ссылку на объект:

#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> ... = {...};

2 голосов
/ 13 декабря 2011

(*VecPtr)[0] совершенно нормально, но вы можете использовать функцию at, если хотите:

VecPtr->at(0);

Имейте в виду, что это (в отличие от operator[]) вызовет исключение std::out_of_range, если индекс не находится в диапазоне.

1 голос
/ 03 ноября 2015

Стоит отметить, что в C ++ 11 std :: vector имеет функцию-член «data», которая возвращает указатель на базовый массив (как константной, так и неконстантной версий), что позволяет вам написать следующее:

VecPtr->data()[0];

Это может быть альтернативой

VecPtr->at(0);

, что приводит к небольшим накладным расходам времени выполнения, но, что более важно, его использование подразумевает, что вы не проверяете индекс на достоверность перед его вызовом, что не так в вашем конкретном примере.

Подробнее см. std :: vector :: data .

0 голосов
/ 16 июля 2016

Люди советуют вам использовать ->at(0) из-за проверки диапазона.Но вот мой совет (с другой точки зрения):

НИКОГДА не используйте ->at(0)!Это действительно медленнее.Вы бы пожертвовали производительностью только потому, что достаточно ленивы, чтобы не проверять дальность самостоятельно?Если это так, вы не должны программировать на C ++.

Я думаю, (*VecPtr)[0] в порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...