![]() |
Форум сайта insidecpp.ru.
Вы не вошли.
Собственно, сабж.
У кого-то из столпов С++-изма встречал разъяснение, что первый метод лучше. Сейчас уже не помню у кого (вроде Мейерс). Что по этому поводу думает многоуважаемый All?
Неактивен
правильно, Мейерс. речь идет об STL.
-> - можно перегрузить. и STL не накладывает ограничение.
а вот (*it) _обязан_ возвращать ссылку на объект
Неактивен
RedLord
Так ведь и операцию разыменования можно перегружать ;-)
Неактивен
да операцию разыменования можно перегрузить, но я специально указал, что речь идет об STL.
C++ 14882:
All iterators i support the expression *i, resulting in a value
of some class, enumeration, or built-in type T, called the value type of the iterator. All iterators i for which
the expression (*i).m is well-defined, support the expression i->m with the same semantics as (*i).m.
для i-> результат может быть не T*
Отредактированно RedLord (2007-09-25 21:50:10)
Неактивен
RedLord написал:
-> - можно перегрузить. и STL не накладывает ограничение.
а вот (*it) _обязан_ возвращать ссылку на объект
#include <iostream>
class X
{
public:
void f() { std::cout << "Yoyo!\n"; }
int i;
};
int main()
{
X *x = 0;
(*x).f();
std::cout << x->i << "\n";
return 0;
}
Вывод:
Yoyo!
Segmentation fault
Обращение к x->i, конечно, уронило программу, а вот (*x).f() сработало :) Компилятор GNU g++ v4.2.3, с ключом -O0 Это иллюстрирует, что запись (*x).<чтонибудь> вовсе не означает, что кто-то что-то здесь будет разыменовывать. (*x) или x-> означает принадлежность функции к типу, и только. А вот область памяти, на которую указывает ее неявный аргумент this, ей понадобится только тогда, когда в теле ф-ции будет обращение к полям типа. Если обращение по адресу this не требуется, можно запросто сделать ((X *)чтоугодно)->f(), и это будет работать.
Отредактированно indexless (2008-02-21 22:22:24)
Неактивен
indexless
В вашем примере x->f() сработает, а (*x).i - нет. Вы верно сказали, что падение будет только если функция обратится к членам класса, но в вашем примере никакой разницы между operator . и operator -> нет.
Неактивен
Да, стандарт требует. Но есть НО.
Это "но" начинает проявляться тогда, когда вы работаете с контейнером интеллектуальных указателей (например shared_ptr). У этих товарищей, как известно, перегружен оператор ->. Так вот, если вы хотете вызвать функцию класса, объектом которого владеет такой указатель, через итератор на него, то вам нужно использовать что-то типа iter->->foo(). А это, понятное дело, не поддерживается. Так что только (*iter)->foo().
Таким образом, код "знает" что именно хранится в контейнере. А это абсолютно неприемлемо для обобщённого кода. И, естественно, не годится при написании расширений STL. (см. Willson)
Так что? работать с разыменованым итератором это более обобщённо. И вообще, это хорошая привычка ("выдох в воду") (от меня респект автору за хорошую метафору).
Неактивен
addword написал:
Так вот, если вы хотете вызвать функцию класса, объектом которого владеет такой указатель, через итератор на него, то вам нужно использовать что-то типа iter->->foo(). А это, понятное дело, не поддерживается. Так что только (*iter)->foo().
Еще можно iter->get()->foo(); :)
Неактивен
Да, так тоже можно. Но я рекомендую использовать технику разыменования итератора. Это так сказать, хорошая привычка, "выдох под воду" (см. статью в разделе "Арт").
Как я уже говорил, это неприемлемо для обобщённого кода.
Код из примера с использованием get(), подходит для случаев когда в контейнере хранятся не указатели, а объекты класса, предоставляющего функцию get(), возвращающую указатель. То есть код получился ещё менее обобщённым.
Неактивен
| Статистика |
|
|