Malabarba
Malabarba

Reputation: 4553

Accessing the [] operator from a pointer

If I define a pointer to an object that defines the [] operator, is there a direct way to access this operator from a pointer?

For example, in the following code I can directly access Vec's member functions (such as empty()) by using the pointer's -> operator, but if I want to access the [] operator I need to first get a reference to the object and then call the operator.

#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;
}

I might very well be wrong, but it looks like doing (*VecPtr).empty() is less efficient than doing VecPtr->empty(). Which is why I was looking for an alternative to (*VecPtr)[].

Upvotes: 47

Views: 29530

Answers (7)

KinGamer
KinGamer

Reputation: 509

There's another way, you can use a reference to the object:

#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;
}

This way, r is the same as v and you can substitute all occurrences of (*p) by r.

Caveat: This will only work if you won't modify the pointer (i.e. change which object it points to).

Consider the following:

#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; is wrong because you can't change references: This will modify the vector referenced by r (v) instead of referencing another vector (u). So, again, this only works if the pointer won't change while still using the reference.

The examples need C++11 only because of vector<int> ... = {...};

Upvotes: 4

user3785008
user3785008

Reputation: 85

People are advising you to use ->at(0) because of range checking. But here is my advise (with other point of view):

NEVER use ->at(0)! It is really slower. Would you sacrifice performance just because you are lazy enough to not check range by yourself? If so, you should not be programming in C++.

I think (*VecPtr)[0] is ok.

Upvotes: -3

Jan Holecek
Jan Holecek

Reputation: 2241

It is worth noting that in C++11 std::vector has a member function 'data' that returns a pointer to the underlying array (both const and non-const versions), allowing you to write the following:

VecPtr->data()[0];

This might be an alternative to

VecPtr->at(0);

which incurs a small runtime overhead, but more importantly it's use implies you aren't checking the index for validity before calling it, which is not true in your particular example.

See std::vector::data for more details.

Upvotes: 1

Robᵩ
Robᵩ

Reputation: 168626

You could do any of the following:

#include <vector>

int main () {
  std::vector<int> v(1,1);
  std::vector<int>* p = &v;

  p->operator[](0);
  (*p)[0];
  p[0][0];
}

By the way, in the particular case of std::vector, you might also choose: p->at(0), even though it has a slightly different meaning.

Upvotes: 56

Tam&#225;s Szelei
Tam&#225;s Szelei

Reputation: 23931

(*VecPtr)[0] is perfectly OK, but you can use the at function if you want:

VecPtr->at(0);

Keep in mind that this (unlike operator[]) will throw an std::out_of_range exception if the index is not in range.

Upvotes: 4

lapk
lapk

Reputation: 3918

You can use it as VecPrt->operator [] ( 0 ), but I'm not sure you'll find it less obscure.

Upvotes: 3

Sean
Sean

Reputation: 29772

return VecPtr->operator[](0);

...will do the trick. But really, the (*VecPtr)[0] form looks nicer, doesn't it?

Upvotes: 12

Related Questions