Pergunta

When iterating over an vector (or other container) of pointers, is there any difference between and/or over advantage using:

for (it = v.begin(); it != v.end(); ++it) {
    (*it)->method();
}

or

for (it = v.begin(); it != v.end(); ++it) {
    (**it).method();
}
Foi útil?

Solução

In the C language, there is no difference. However, in C++, the -> operator can be overloaded, whereas the member selection . operator cannot.

So in (*foo)->bar *foo could designate a class object which acts as a smart pointer, though this won't happen if foo is an iterator over a standard C++ container of pointers, which means that *foo evaluates to a pointer.

And in (**foo).bar, **foo has to be a class object with a member called bar (which is accessible).

The unary * can also be overloaded (which is how the iterator foo, a class object, returns the object which it references).

In other words, the expressions can diverge in meaning, but if *foo is a pointer to a class/struct, then the equivalence inherited from the C language applies: (*ptr).member is equivalent to ptr->member.

Outras dicas

They are equivalent: as defined the standard (for pointers)

5.2.5 Class member access [expr.ref]
2: For the first option (dot) the first expression shall have complete class type. For the second option (arrow) the first expression shall have pointer to complete class type. The expression E1->E2 is converted to the equivalentform(*(E1)).E2; the remainder of 5.2.5 will address only the first option (dot).65 In either case, the id-expression shall name a member of the class or of one of its base classes.

Classes and overriding the -> and * operator are not relevant here as the container contains pointers.

Thus:

(*it)->method();

// Is equivelent to:

(*((*it))).method();

// This is equivelent too:

(**it).method(); // thus both expressions are identical in this context.

No. -> just says to access the struct as a pointer. . acts as if it's just a struct. It's synactic - there's no difference in terms of functionality.

Edit: You can overload -> to make it do something different, although assuming you don't do that it's the same. Not sure why you'd do that, but if you did then you'd have to dereference your struct again using an additional *.

They're the same. You can use one or the other depending on the coding conventions you use, for example.

-> and * operators can be overloaded, while . operator cannot.

On Ubuntu 12.04 a list iterator implemented in the following way:

template<typename _Tp>
struct _List_iterator
{

  // ...
  reference
  operator*() const
  { return static_cast<_Node*>(_M_node)->_M_data; }

  pointer
  operator->() const
  { return std::__addressof(static_cast<_Node*>(_M_node)->_M_data); }

  // ...
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top