разница между foo [i] и foo-> at (i) с вектором stl - PullRequest
3 голосов
/ 14 января 2010

есть ли причина, по которой

foo = (bar-> at (x)) -> at (y);

работает, но

foo = bar [x] [y];

не работает, где bar - вектор векторов (используется c ++ stl)

декларация:

std :: vector *>

Ответы [ 7 ]

9 голосов
/ 14 января 2010

Это вектор векторов или вектор указателей на векторы? Ваш код должен работать как рекламируется :

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] = /* ... */;

Но ваш код выглядит так:

typedef std::vector<vec_int*> multi_int; // pointer!
multi_int* m; // more pointer!

Если у вас есть указатели, вам нужно сначала разыменовать их, чтобы использовать operator[]:

(*(*m)[2])[2] = /* ... */;

Это может быть ужасно. Возможно временно использовать ссылки:

multi_int& mr = m;
(*mr[2])[2] = /* ... */;

Хотя это все еще некрасиво. Может быть полезны бесплатные функции:

template <typename T>
typename T::value_type& access_ptr(T* pContainer,
                                    unsigned pInner, unsigned pOuter)
{
    return (*(*pContainer)[pInner])[pOuter]);
}

access_ptr(m, 2, 2) = /* ... */

Однако наиболее предпочтительным является избавление от указателей . Указатели могут просачиваться и вызывать всевозможные проблемы, например утечку при возникновении исключений. Если вы должны использовать указатели, используйте контейнер указателя от boost для внутреннего вектора и сохраните фактический объект в интеллектуальном указателе .

Кроме того, ваш заголовок немного вводит в заблуждение. Разница между at и operator[] заключается в том, что at выполняет проверку диапазона. В остальном они одинаковые.

4 голосов
/ 14 января 2010

Вы уверены, что у вас есть вектор векторов? Если вы сделали тогда

foo = bar[x][y];

будет похоже на

foo = bar.at(x).at(y);

, но без проверки диапазона и поведения исключения at.

Если bar->at(x)->at(y) работает, то это, вероятно, будет несколько эквивалентно (*(*bar)[x])[y], а не bar[x][y], но должно означать, что bar не является вектором векторов.

1 голос
/ 14 января 2010

Казалось бы, у вас есть указатель на вектор указателей на векторы ...

Так что, если вы хотите сделать то, что пытались, вам понадобится

foo = (* ((* bar) [x])) [Y];

Используйте вектор векторов (т.е. взамен std :: vector >.

Редактировать: Также стоит отметить, что at делает некоторые проверки диапазона, поэтому, если вам не нужны эти проверки диапазона, это медленнее, чем использование оператора [].

1 голос
/ 14 января 2010

, если bar - указатель, сначала нужно разыменовать его:

(*bar)[x][y]

если указатель на вектор векторных указателей:

(*(*bar)[x])[y]

as R Samuel Klatchko и другие упомянутые

1 голос
/ 14 января 2010

Что ж, если bar является указателем (как предлагает первый пример), вам нужно переписать второй пример:

(*(*foo)[x])[y]
0 голосов
/ 14 января 2010

Для

foo = (bar->at(x))->at(y);

для работы bar должен быть указателем, а вектор, на который он указывает, должен содержать указатели.

Для

foo = bar[x][y];

для работы bar должен быть vector (не указатель), который содержит векторы (не указатели).

0 голосов
/ 14 января 2010

Зависит от того, как вы определяете «работает» и «не работает». Что происходит, когда это «не работает»? Основное различие между ними заключается в том, что at выполняет проверку границ, а operator[] - нет.

Но в вашем случае проблема в том, что bar - это , а не вектор векторов. Кажется, это указатель на вектор указателей на векторы. (Что само по себе является плохим признаком. Вероятно, это не обязательно должен быть указатель. Все также динамически выделяется с помощью new? Не делайте этого по умолчанию)

А это значит, что вы пытаетесь вызвать operator[] по указателю, а не по вектору - который определен, но делает что-то другое, чем вы ожидаете. Код во втором случае фактически эквивалентен (*(bar+x))[y] - и кроме выхода за пределы, дающего неопределенное поведение, результатом будет указатель на вектор любого типа foo, а не элемент этого вектора.

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