Accessing the [] operator from a pointer

22,816

Solution 1

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.

Solution 2

return VecPtr->operator[](0);

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

Solution 3

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

Solution 4

(*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.

Solution 5

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

Share:
22,816
Malabarba
Author by

Malabarba

I: am the author of Endless Parentheses; help manage and develop CIDER, the most widely used Clojure IDE; help develop GNU Emacs when I have time; author and manage a number of open source projects, among which: Paradox: Modernized Package Menu for Emacs. sx.el: Full-feature Emacs client for StackOverflow, Super User, and the entire Stack Exchange network. aggressive-indent-mode: Minor mode that keeps your code permanently indented. smart-mode-line: A powerful and beautiful mode-line for Emacs. The Bug-Hunter: Hunt down errors in elisp files. names: A namespace system for elisp.

Updated on July 09, 2022

Comments

  • Malabarba
    Malabarba almost 2 years

    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)[].

    • matth
      matth over 12 years
      Why do you want to avoid (*VecPtr)[0] ?
    • Malabarba
      Malabarba over 12 years
      @Rob Edited with a reason. My assumption might be wrong, but it's why I asked.
    • UncleBens
      UncleBens over 12 years
      (*VecPtr).empty() and VecPtr->empty() are exactly the same thing (unless VecPtr is something that overloads operator* and operator-> with conflicting meaning.
    • matth
      matth over 12 years
      If VecPtr is a pointer type, then (*VecPtr).XXX is, by definition, equivalent to VecPtr->XXX. There is no loss of efficiency. If VecPtr is a non-pointer type that implements operator* and operator[], then you'll have to examine them to see which is more efficient (they are probably the same).
    • Kerrek SB
      Kerrek SB over 12 years
      How is this question getting upvoted?? It is based on one of the most ill-informed and under-researched premises and hardly of value to others.
  • Nick
    Nick over 6 years
    why at(0) is slow?
  • Theko Lekena
    Theko Lekena about 6 years
    That last one there is interesting, could you explain what is happening there under the hood? Is that first [0] referring to the "first element" pointed to by the pointer? Similar to how a vector reference is a pointer to the beginning to an array?
  • M.M
    M.M over 5 years
    r = u; is fine and it will do assignment between the two vectors ; this has nothing to do with p
  • KinGamer
    KinGamer over 5 years
    And this is what I mean by "wrong". Quoting myself, "you can substitute all occurrences of (*p) by r", but "This will only work if you won't modify the pointer", because there's no way to change r as you would change the value of *p. r = u; "will modify the vector referenced by r instead of referencing another vector" -- it won't have the intended effect.
  • M.M
    M.M over 5 years
    r = u; will have the same effect whether or not you later modify the pointer
  • KinGamer
    KinGamer over 5 years
    Yes, but I don't get why you're saying that. Again, by "wrong" I mean it doesn't do what p = ... would do. And I'm talking about substituting all ocurrences of *p by r. But if in your code you have p = ..., replacing p = ... by r = ... is wrong.
  • LeonTheProfessional
    LeonTheProfessional almost 4 years
    @ThekoLekena exactly, for pointers to complete-types T, the [] operator is defined to access the ith element of the array (by calculating sizeof(T) * i). Of course, since in this case we have a pointer to one vector, having anything else than [0] would be undefined behaviour. edit: i wouldn't choose the last one though, as i find it less idiomatic.
  • Theko Lekena
    Theko Lekena almost 4 years
    @ancientchild agreed, the last one should not be used as normal practice.