is there any reason why
foo = (bar->at(x))->at(y);
works but
foo = bar[x][y];
does not work, where bar is a vector of vectors (using the c++ stl)
the declaration is:
std::vector< std::vector < Object * > * >
is there any reason why
foo = (bar->at(x))->at(y);
works but
foo = bar[x][y];
does not work, where bar is a vector of vectors (using the c++ stl)
the declaration is:
std::vector< std::vector < Object * > * >
Are you sure you have a vector of vectors? If you did then
foo = bar[x][y];
would be like
foo = bar.at(x).at(y);
but without the range checking and exception behaviour of at
.
If bar->at(x)->at(y)
works, then this is likely to be somewhat equivalent to (*(*bar)[x])[y]
and not bar[x][y]
but must mean that bar
isn't a vector of vectors.
Well, if bar is a pointer (as the first example suggests), you would need to rewrite your second example to:
(*(*foo)[x])[y]
if bar is a pointer, you'd want to dereference it first:
(*bar)[x][y]
if its a pointer to a vector of vector pointers:
(*(*bar)[x])[y]
as R Samuel Klatchko and others mentioned
Is it a vector of vectors or a vector of pointers to vectors? Your code should work as advertised:
typedef std::vector<int> vec_int;
typedef std::vector<vec_int> multi_int;
multi_int m(10, vec_int(10));
m.at(2).at(2) = /* ... */;
m[2][1] = /* ... */;
But your code appears to have:
typedef std::vector<vec_int*> multi_int; // pointer!
multi_int* m; // more pointer!
If you have pointers, you'll need to dereference them first to use operator[]
:
(*(*m)[2])[2] = /* ... */;
That that can be ugly. Maybe use references temporarily:
multi_int& mr = m;
(*mr[2])[2] = /* ... */;
Though that still has some ugly. Maybe free-functions are helpful:
template <typename T>
typename T::value_type& access_ptr(T* pContainer,
unsigned pInner, unsigned pOuter)
{
return (*(*pContainer)[pInner])[pOuter]);
}
access_ptr(m, 2, 2) = /* ... */
Most preferable is to be rid of the pointers, though. Pointers can leak and have all sorts of problems, like leaking when exceptions are thrown. If you must use pointers, use a pointer container from boost for the inner vector, and store the actual object in a smart pointer.
Also, your title is a bit misleading. The difference between at
and operator[]
is that at
does range checks. Otherwise, they are the same.
Depends on how you define "works" and "doesn't work". What happens when it "doesn't work"?
The main difference between the two is that at
performs bounds-checking, which operator[]
does not.
But in your case, the problem is that bar
is not a vector of vectors. It seems to be a pointer to a vector of pointers to vectors. (Which in itself is a bad sign. It probably doesn't need to be a pointer. Is everything also dynamically allocated with new
? Don't do that by default)
And that means that you're trying to invoke operator[]
on a pointer, not a vector -- which is defined, but does something other than you expect. The code in your second case is effectively equivalent to (*(bar+x))[y]
- and apart from going out of bounds yielding undefined behavior, the result would be a pointer to a vector of whatever type foo is, rather than an element of that vector.
It would seem you have a pointer to a vector of pointers to vectors ...
So if you want to do as you've tried you'd need
foo = (*((*bar)[x]))[Y];
Use a vector of vectors (ie std::vector< std::vector< datatype > > instead.
Edit: Also worth noting that at does do some range checks so, provided you don't need those range checks, is slower than using operator[].
For
foo = (bar->at(x))->at(y);
to work bar
would have to be a pointer and the vector it points to would have to contain pointers.
For
foo = bar[x][y];
to work, bar
would have to be a vector
(not a pointer) that contained vectors (not pointers).