Страницы

Поиск по вопросам

среда, 4 декабря 2019 г.

Как правильно использовать std::begin и std::end?

#cpp #cpp11


Начиная с С++11, в стандарт были добавлены функции std::begin и std::end, которые
можно использовать вместо методов .begin() и .end().

Как и когда их надо использовать?
    


Ответы

Ответ 1



Наиболее известное свойство функций std::begin и std::end - это то, что они работают с массивами: int a[3] = {1, 2, 3}; int sum = std::accumulate(std::begin(a), std::end(a), 0); Для контейнеров-классов, если тип контейнера известен, единственное преимущество свободной функции std::begin() перед функцией-членом - это то, что код получается на один символ короче: std::vector v = {1, 2, 3}; std::reverse(begin(v), end(v)); std::reverse(v.begin(), v.end()); Здесь префикс std:: указывать не надо, т.к. работает поиск имен, зависящих от аргументов (ADL): vector находится в пространстве имен std, по этому для него будет найдена функция std::begin (из того же пространства имен). В обобщенном коде надо использовать using std::begin; Так как существует поиск имен (ADL), то нужные функции begin и end могут находиться в другом пространстве имен (не std). Однако с массивами работают только функции из std, по этому в шаблонных функциях надо явно добавлять std::begin и std::end в область видимости: template int sum(Container& c) { using std::begin; // Поиск имен также будет искать std::begin. using std::end; return std::accumulate(begin(c), end(c), 0); } Если сюда передать контейнер-класс, который находится в каком-либо пространстве имен, то будут использованы функции begin() и end() из этого пространства имен. Если же таких функций нет, или Container - это обычный массив, то будут вызваны функции std::begin и std::end. Для контейнеров-классов будут вызваны методы .begin() и .end(). Это можно продемонстрировать следующим примером (Код полностью) struct GlobalArray { ... int* begin() { return arr; } int* end() { return arr + N; } }; namespace ns { struct Array {...}; int* begin(Array& a); int* end(Array& a); } int main() { ns::Array ns_arr; for (auto& x : ns_arr) x = 1; // В sum() будут использованы ns::begin и ns::end std::cout << sum(ns_arr) << '\n'; std::vector v = {1, 20, 300}; // Будут использованы std::begin и std::end, которые вызовут методы .begin() и .end() std::cout << sum(v) << '\n'; int c_arr[] = {400, 50, 6}; // Будут использованы std::begin и std::end std::cout << sum(c_arr) << '\n'; GlobalArray glob_arr; for (auto& x : glob_arr) x = 1; // Будут использованы std::begin и std::end, которые вызовут методы .begin() и .end() std::cout << sum(glob_arr) << '\n'; }

Комментариев нет:

Отправить комментарий