Spec-Zone.ru › C++

std::map<Key,T,Compare,Allocator>::map

map();
(1) (до C++11)
map()
    : map(Compare()) {}
(начиная с C++11)
explicit map( const Compare& comp,
              const Allocator& alloc = Allocator() );
(2)
explicit map( const Allocator& alloc );
(3) (начиная с C++11)
template< class InputIt >
map( InputIt first, InputIt last,
     const Compare& comp = Compare(),
     const Allocator& alloc = Allocator() );
(4)
template< class InputIt >
map( InputIt first, InputIt last,
     const Allocator& alloc )
    : map(first, last, Compare(), alloc) {}
(5) (начиная с C++14)
map( const map& other );
(6)
map( const map& other, const Allocator& alloc );
(7) (начиная с C++11)
map( map&& other );
(8) (начиная с C++11)
map( map&& other, const Allocator& alloc );
(9) (начиная с C++11)
map( std::initializer_list<value_type> init,
     const Compare& comp = Compare(),
     const Allocator& alloc = Allocator() );
(10) (начиная с C++11)
map( std::initializer_list<value_type> init,
     const Allocator& alloc )
    : map(init, Compare(), alloc) {}
(11) (начиная с C++14)
template< container-compatible-range<value_type> R >
map( std::from_range_t, R&& rg,
     const Compare& comp = Compare(),
     const Allocator& alloc = Allocator() );
(12) (начиная с C++23)
template< container-compatible-range<value_type> R >
map( std::from_range_t, R&& rg,
     const Allocator& alloc )
    : map(std::from_range, std::forward<R>(rg), Compare(), alloc) {}
(13) (начиная с C++23)

Создаёт новый контейнер из различных источников данных, при необходимости используя предоставленный пользователем распределитель памяти alloc или объект-функцию сравнения comp.

1-3) Создаёт пустой контейнер.
4,5) Создаёт контейнер, содержащий элементы диапазона [first, last). Если несколько элементов в диапазоне имеют ключи, сравниваемые как эквивалентные, не указано, какой именно элемент будет вставлен (ожидается решение LWG2844).
Если [first, last) не является допустимым диапазоном, поведение не определено.
6,7) Конструктор копирования. Создаёт контейнер, содержащий копию элементов other.

Если alloc не указан, распределитель памяти получается вызовом

std::allocator_traits<allocator_type>::
    select_on_container_copy_construction(other.get_allocator())
(начиная с C++11)

При выведении аргументов шаблона класса только первый аргумент участвует в выводе параметра шаблона контейнера Allocator.

(начиная с C++23)
8,9) Конструктор перемещения. Создаёт контейнер, содержащий элементы other, используя семантику перемещения. Если alloc не указан, распределитель памяти создаётся перемещающим конструированием из распределителя памяти, принадлежащего other.

При выведении аргументов шаблона класса только первый аргумент участвует в выводе параметра шаблона контейнера Allocator.

(начиная с C++23)
10,11) Конструктор со списком инициализаторов. Создаёт контейнер, содержащий элементы списка инициализаторов init.Если несколько элементов в диапазоне имеют ключи, сравниваемые как эквивалентные, не указано, какой именно элемент будет вставлен (ожидается решение LWG2844).
12,13) Создаёт контейнер, содержащий элементы rg. Если несколько элементов в диапазоне имеют ключи, сравниваемые как эквивалентные, не указано, какой именно элемент будет вставлен (ожидается решение LWG2844).

Параметры

alloc - распределитель памяти, используемый для всех выделений памяти этим контейнером
comp - объект-функция сравнения, используемый для всех сравнений ключей
first, last - пара итераторов, задающая исходный диапазон копируемых элементов
other - другой контейнер, используемый в качестве источника для инициализации элементов контейнера
init - список инициализаторов для инициализации элементов контейнера
rg - диапазон, совместимый с контейнером, то есть input_range, элементы которого преобразуемы в value_type
Требования к типам
-InputIt должен соответствовать требованиям LegacyInputIterator.
-Compare должен соответствовать требованиям Compare.
-Allocator должен соответствовать требованиям Allocator.

Сложность

1-3) Константная.
4,5) \(\scriptsize N \cdot log(N)\)N·log(N), где \(\scriptsize N\)N — std::distance(first, last); в общем случае, линейная по \(\scriptsize N\)N, если [first, last) уже отсортирован по value_comp().
6,7) Линейная относительно размера other.
8,9) Константная. Если указан alloc и alloc != other.get_allocator(), то линейная.
10,11) \(\scriptsize N \cdot log(N)\)N·log(N), где \(\scriptsize N\)N — init.size(); в общем случае, линейная по \(\scriptsize N\)N, если init уже отсортирован по value_comp().
12,13) \(\scriptsize N \cdot log(N)\)N·log(N), где \(\scriptsize N\)N — ranges::distance(rg); в общем случае, линейная по \(\scriptsize N\)N, если rg уже отсортирован по value_comp().

Исключения

Вызовы Allocator::allocate могут привести к исключению.

Примечания

После перемещающего конструирования контейнера (перегрузка (8,9)) ссылки, указатели и итераторы, которые изначально указывали на элементы other, остаются действительными, но теперь указывают на элементы *this. Действующий стандарт гарантирует это общим утверждением в [container.reqmts]/67; в настоящее время рассматривается возможность более прямой гарантии посредством предложения LWG 2321.

Хотя формально это не требовалось до C++23, некоторые реализации уже помещали параметр шаблона Allocator в невыводимые контексты в более ранних режимах.

Макрос проверки поддержки возможности Значение Стандарт Возможность
__cpp_lib_containers_ranges 202202L (C++23) Конструирование и вставка с поддержкой диапазонов; перегрузки (12,13)

Пример

#include <iomanip>
#include <iostream>
#include <map>
#include <string>

template<typename Key, typename Value, typename Cmp>
std::ostream& operator<<(std::ostream& os, std::map<Key, Value, Cmp> const& map)
{
    os << "{ ";
    for (auto comma{map.size()}; auto const& p : map)
        os << '\'' << p.first << "' is " << p.second << (--comma ? ", " : " ");
    return os << "}\n";
}

struct Point
{
    double x, y;
    
    friend std::ostream& operator<<(std::ostream& os, Point pt)
    {
        return os << '(' << pt.x << ", " << pt.y << ')';
    }
};

struct PointCmp
{
    bool operator()(const Point& lhs, const Point& rhs) const
    {
        return lhs.x < rhs.x; // NB: y is intentionally ignored
    }
};

int main()
{
    // (1) Default constructor
    std::map<std::string, int> map1;
    map1["something"] = 69;
    map1["anything"] = 199;
    map1["that thing"] = 50;
    std::cout << "map1 = " << map1;

    // (4) Range constructor
    std::map<std::string, int> iter(map1.find("anything"), map1.end());
    std::cout << "\niter = " << iter;
    std::cout << "map1 = " << map1;

    // (6) Copy constructor
    std::map<std::string, int> copied(map1);
    std::cout << "\ncopied = " << copied;
    std::cout << "map1 = " << map1;

    // (8) Move constructor
    std::map<std::string, int> moved{std::move(map1)};
    std::cout << "\nmoved = " << moved;
    std::cout << "map1 = " << map1;

    // (10) Initializer list constructor
    const std::map<std::string, int> init
    {
        {"this", 100},
        {"can", 100},
        {"be", 100},
        {"const", 100}
    };
    std::cout << "\ninit = " << init;

    std::cout << "\nCustom Key class option 1:\n";
    // Use a comparison struct
    std::map<Point, double, PointCmp> mag =
    {
        {{5, -12}, 13},
        {{3, 4}, 5},
        {{-8, -15}, 17}
    };
    std::cout << "mag = " << mag << '\n';

    std::cout << "Custom Key class option 2:\n";
    // Use a comparison lambda
    // This lambda sorts points according to their magnitudes, where
    // these magnitudes are taken from the local variable mag.
    auto cmpLambda = [&mag](const Point& lhs, const Point& rhs)
    {
        return mag[lhs] < mag[rhs];
    };

    // You could also use a lambda that is not dependent on local variables, like this:
    // auto cmpLambda = [](const Point& lhs, const Point& rhs){ return lhs.y < rhs.y; };
    std::map<Point, double, decltype(cmpLambda)> magy(cmpLambda);

    // Various ways of inserting elements:
    magy.insert(std::pair<Point, double>({5, -12}, 13));
    magy.insert({{3, 4}, 5});
    magy.insert({Point{-8.0, -15.0}, 17});    
    std::cout << "magy = " << magy << '\n';

    std::cout << "Construction from a range:\n";
    using PS = std::pair<const std::string, int>;
    const auto rg = {PS{"one", 1}, {"one", 101}, {"two", 2}, {"three", 3}};
#if __cpp_lib_containers_ranges
    std::map<std::string, int> nums(std::from_range, rg); // overload (12)
#else
    std::map<std::string, int> nums(rg.begin(), rg.end()); // fallback to (4)
#endif
    std::cout << "nums = " << nums << '\n';
}

Вывод:

map1 = { 'anything' is 199, 'something' is 69, 'that thing' is 50 }

iter = { 'anything' is 199, 'something' is 69, 'that thing' is 50 }
map1 = { 'anything' is 199, 'something' is 69, 'that thing' is 50 }

copied = { 'anything' is 199, 'something' is 69, 'that thing' is 50 }
map1 = { 'anything' is 199, 'something' is 69, 'that thing' is 50 }

moved = { 'anything' is 199, 'something' is 69, 'that thing' is 50 }
map1 = { }

init = { 'be' is 100, 'can' is 100, 'const' is 100, 'this' is 100 }

Custom Key class option 1:
mag = { '(-8, -15)' is 17, '(3, 4)' is 5, '(5, -12)' is 13 }

Custom Key class option 2:
magy = { '(3, 4)' is 5, '(5, -12)' is 13, '(-8, -15)' is 17 }

Construction from a range:
nums = { 'one' is 1, 'three' is 3, 'two' is 2 }

Отчёты об ошибках

Следующие отчёты об ошибках, изменяющие поведение, были применены ретроспективно к ранее опубликованным стандартам C++.

DR Применён к Поведение согласно опубликованной версии Корректное поведение
LWG 2076 C++11 перегрузка (4) при определённых условиях требовала, чтобы Keyи T были CopyInsertable в *this не требуется
LWG 2193 C++11 конструктор по умолчанию был явным сделан неявным

См. также

operator=
присваивает значения контейнеру
(открытая функция-член)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/container/map/map

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API