Standard Template Library (STL) - std::map::insert

Standard Template Library (STL) - std::map::insert

public member function - 公开成员函数

1. std::map::insert

C++98
single element (1) pair<iterator,bool> insert (const value_type& val);
with hint (2) iterator insert (iterator position, const value_type& val);
range (3)
template <class InputIterator>
void insert (InputIterator first, InputIterator last);

C++11
single element (1)
pair<iterator,bool> insert (const value_type& val);
template <class P> pair<iterator,bool> insert (P&& val);
with hint (2)
iterator insert (const_iterator position, const value_type& val);
template <class P> iterator insert (const_iterator position, P&& val);
range (3)
template <class InputIterator>
void insert (InputIterator first, InputIterator last);
initializer list (4) void insert (initializer_list<value_type> il);

Insert elements - 插入元素或结点 (C++17 起)

若容器尚未含有带等价关键的元素,则插入元素到容器中。

Extends the container by inserting new elements, effectively increasing the container size by the number of elements inserted.
通过插入新元素来扩展容器,从而通过插入的元素数量有效地增加容器的大小。

Because element keys in a map are unique, the insertion operation checks whether each inserted element has a key equivalent to the one of an element already in the container, and if so, the element is not inserted, returning an iterator to this existing element (if the function returns a value).
由于 map 中的元素键是唯一的,因此插入操作将检查每个插入的元素是否具有与容器中已有元素相同的键,如果是,则不插入该元素,将迭代器返回到此现有元素 (如果函数返回值)。

For a similar container allowing for duplicate elements, see multimap.
有关允许重复元素的类似容器,请参见 multimap

An alternative way to insert elements in a map is by using member function map::operator[].
在 map 中插入元素的另一种方法是使用成员函数 map::operator[]

Internally, map containers keep all their elements sorted by their key following the criterion specified by its comparison object. The elements are always inserted in its respective position following this ordering.
在内部,map 容器会按照其比较对象指定的条件,按其键对所有元素进行排序。始终按照此顺序将元素插入其各自的位置。

The parameters determine how many elements are inserted and to which values they are initialized:
这些参数确定要插入多少个元素以及将它们初始化为哪些值:

2. Parameters

val
Value to be copied to (or moved as) the inserted element.
要复制到 (或移动为) 插入元素的值。

Member type value_type is the type of the elements in the container, defined in map as pair<const key_type,mapped_type> (see map member types).
成员类型 value_type 是容器中元素的类型,在映射中定义为 pair<const key_type,mapped_type> (请参阅 map 成员类型)。

C++98
The template parameter P shall be a type convertible to value_type.
模板参数 P 应为可转换为 value_type 的类型。

C++14
The signatures taking an argument of type P&& are only called if std::is_constructible<value_type,P&&> is true.
仅当 std::is_constructible<value_type,P&&>true 时,才会调用带有 P&& 类型参数的签名。

If P is instantiated as a reference type, the argument is copied.
如果将 P 实例化为引用类型,则将复制参数。

position
Hint for the position where the element can be inserted.
提示可以插入元素的位置。

C++98
The function optimizes its insertion time if position points to the element that will precede the inserted element.
如果位置指向插入元素之前的元素,则该函数将优化其插入时间。

C++11
The function optimizes its insertion time if position points to the element that will follow the inserted element (or to the end, if it would be the last).
如果位置指向将要插入的元素之后的元素 (或者如果它是最后一个,则指向末尾),该函数将优化其插入时间。

Notice that this is just a hint and does not force the new element to be inserted at that position within the map container (the elements in a map always follow a specific order depending on their key).
请注意,这只是一个提示,并不强制将新元素插入到 map 容器中的该位置 (map 中的元素始终根据其键遵循特定顺序)。

Member types iterator and const_iterator are defined in map as bidirectional iterator types that point to elements.
成员类型的迭代器和 const_iterator 在 map 中定义为指向元素的双向迭代器类型。

first, last
Iterators specifying a range of elements. Copies of the elements in the range [first, last) are inserted in the container.
指定元素范围的迭代器。范围为 [first, last) 的元素副本插入到容器中。

Notice that the range includes all the elements between first and last, including the element pointed by first but not the one pointed by last.
请注意,范围包括 first 和 last 之间的所有元素,包括 first 所指向的元素,但 last 所指向的元素则不包括。

The function template argument InputIterator shall be an input iterator type that points to elements of a type from which value_type objects can be constructed.
函数模板参数 InputIterator 必须是一个输入迭代器类型,该类型指向可以从其构造 value_type 对象的类型的元素。

il
An initializer_list object. Copies of these elements are inserted.
一个 initializer_list 对象。插入这些元素的副本。

These objects are automatically constructed from initializer list declarators.
这些对象是根据初始值设定项列表声明符自动构造的。

Member type value_type is the type of the elements contained in the container, defined in map as pair<const key_type,mapped_type> (see map member types).
成员类型 value_type 是容器中包含的元素的类型,在映射中定义为 pair<const key_type,mapped_type> (请参阅映射成员类型)。

hint [hɪnt]:n. 暗示,线索 vt. 暗示,示意 vi. 示意

3. Return value

The single element versions (1) return a pair, with its member pair::first set to an iterator pointing to either the newly inserted element or to the element with an equivalent key in the map. The pair::second element in the pair is set to true if a new element was inserted or false if an equivalent key already existed.
单个元素版本 (1) 返回一个 pair,其成员 pair::first 设置为一个迭代器,该迭代器指向新插入的元素或指向映射中具有等效键的元素。如果插入了新元素,则对中的 pair::second 元素设置为 true,如果已经存在等效键,则设置为 false。

The versions with a hint (2) return an iterator pointing to either the newly inserted element or to the element that already had an equivalent key in the map.
带有提示 (2) 的版本将返回一个迭代器,该迭代器指向新插入的元素或 map 中已具有等效键的元素。

Member type iterator is a bidirectional iterator type that points to elements.
成员类型迭代器是指向元素的双向迭代器类型。

pair is a class template declared in <utility> (see pair).
对是在 <utility> 中声明的类模板 (请参见对)。

4. Examples

4.1 std::map::insert

//============================================================================
// Name        : std::map::insert (C++98)
// Author      : Yongqiang Cheng
// Version     : Version 1.0.0
// Copyright   : Copyright (c) 2019 Yongqiang Cheng
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <map>

int main()
{
	std::map<char, int> map_data;

	// first insert function version (single parameter):
	map_data.insert(std::pair<char, int>('a', 100));
	map_data.insert(std::pair<char, int>('z', 200));

	std::pair<std::map<char, int>::iterator, bool> ret;
	ret = map_data.insert(std::pair<char, int>('z', 500));
	if (ret.second == false)
	{
		std::cout << "element 'z' already existed";
		std::cout << " with a value of " << ret.first->second << '\n';
	}

	// second insert function version (with hint position):
	std::map<char, int>::iterator it = map_data.begin();
	map_data.insert(it, std::pair<char, int>('b', 300)); // max efficiency inserting
	map_data.insert(it, std::pair<char, int>('c', 400)); // no max efficiency inserting

	// third insert function version (range insertion):
	std::map<char, int> anothermap;
	anothermap.insert(map_data.begin(), map_data.find('c'));

	// showing contents:
	std::cout << "map_data contains:\n";
	for (it = map_data.begin(); it != map_data.end(); ++it)
	{
		std::cout << it->first << " => " << it->second << '\n';
	}

	std::cout << "anothermap contains:\n";
	for (it = anothermap.begin(); it != anothermap.end(); ++it)
	{
		std::cout << it->first << " => " << it->second << '\n';
	}

	return 0;
}

element 'z' already existed with a value of 200
map_data contains:
a => 100
b => 300
c => 400
z => 200
anothermap contains:
a => 100
b => 300

4.2 std::map::insert

//============================================================================
// Name        : std::map::insert (GCC 9.2 (C++17))
// Author      : Yongqiang Cheng
// Version     : Version 1.0.0
// Copyright   : Copyright (c) 2019 Yongqiang Cheng
// Description : Hello World in C++, Ansi-style
//============================================================================

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

using namespace std::literals;

template<typename It>
void printInsertionStatus(It it, bool success)
{
	std::cout << "Insertion of " << it->first << (success ? " succeeded\n" : " failed\n");
}

int main()
{
	std::map<std::string, float> karasunoPlayerHeights;

	// Overload 3: insert from rvalue reference
	const auto [it_hinata, success] = karasunoPlayerHeights.insert({"Hinata"s, 162.8});
	printInsertionStatus(it_hinata, success);

	{
		// Overload 1: insert from lvalue reference
		const auto [it, success2] = karasunoPlayerHeights.insert(*it_hinata);
		printInsertionStatus(it, success2);
	}

	{
		// Overload 2: insert via forwarding to emplace
		const auto [it, success] = karasunoPlayerHeights.insert({"Kageyama", 180.6});
		printInsertionStatus(it, success);
	}

	{
		// Overload 6: insert from rvalue reference with positional hint
		const std::size_t n = std::size(karasunoPlayerHeights);
		const auto it = karasunoPlayerHeights.insert(it_hinata,	{"Azumane"s, 184.7});
		printInsertionStatus(it, std::size(karasunoPlayerHeights) != n);
	}

	{
		// Overload 4: insert from lvalue reference with positional hint
		const std::size_t n = std::size(karasunoPlayerHeights);
		const auto it = karasunoPlayerHeights.insert(it_hinata, *it_hinata);
		printInsertionStatus(it, std::size(karasunoPlayerHeights) != n);
	}

	{
		// Overload 5: insert via forwarding to emplace with positional hint
		const std::size_t n = std::size(karasunoPlayerHeights);
		const auto it = karasunoPlayerHeights.insert(it_hinata,	{"Tsukishima", 188.3});
		printInsertionStatus(it, std::size(karasunoPlayerHeights) != n);
	}

	auto node_hinata = karasunoPlayerHeights.extract(it_hinata);
	std::map<std::string, float> playerHeights;

	// Overload 7: insert from iterator range
	playerHeights.insert(std::begin(karasunoPlayerHeights), std::end(karasunoPlayerHeights));

	// Overload 8: insert from initializer_list
	playerHeights.insert({{"Kozume"s, 169.2}, {"Kuroo", 187.7}});

	// Overload 9: insert node
	const auto status = playerHeights.insert(std::move(node_hinata));
	printInsertionStatus(status.position, status.inserted);

	node_hinata = playerHeights.extract(status.position);
	{
		// Overload 10: insert node with positional hint
		const std::size_t n = std::size(playerHeights);
		const auto it = playerHeights.insert(std::begin(playerHeights),	std::move(node_hinata));
		printInsertionStatus(it, std::size(playerHeights) != n);
	}

	// Print resulting map
	std::cout << std::left << '\n';
	for (const auto& [name, height] : playerHeights)
	{
		std::cout << std::setw(10) << name << " | " << height << "cm\n";
	}

	return 0;
}

GCC 9.2 (C++17)

Insertion of Hinata succeeded
Insertion of Hinata failed
Insertion of Kageyama succeeded
Insertion of Azumane succeeded
Insertion of Hinata failed
Insertion of Tsukishima succeeded
Insertion of Hinata succeeded
Insertion of Hinata succeeded

Azumane    | 184.7cm
Hinata     | 162.8cm
Kageyama   | 180.6cm
Kozume     | 169.2cm
Kuroo      | 187.7cm
Tsukishima | 188.3cm

5. Complexity - 复杂度

If a single element is inserted, logarithmic in size in general, but amortized constant if a hint is given and the position given is the optimal.
如果插入单个元素,则通常与容器大小成对数,但如果给出提示且给定位置为最佳,则摊销常量。

amortize [əˈmɔːtaɪz]:vt. 摊销 (等于 amortise),分期偿还

C++98
If N elements are inserted, Nlog(size+N) in general, but linear in size+N if the elements are already sorted according to the same ordering criterion used by the container.
如果插入了 N 个元素,则通常为 Nlog(size+N),但是如果已经按照容器使用的相同排序标准对元素进行了排序,则通常是 size + N 线性的。

C++11
If N elements are inserted, Nlog(size+N).
Implementations may optimize if the range is already sorted.
如果范围已经排序,则实现可以优化。

6. Iterator validity - 迭代器有效性

No changes.

7. Data races - 数据竞争

The container is modified.
容器已修改。

Concurrently accessing existing elements is safe, although iterating ranges in the container is not.
同时访问现有元素是安全的,尽管容器中的迭代范围并非如此。

8. Exception safety - 异常安全性

If a single element is to be inserted, there are no changes in the container in case of exception (strong guarantee).
如果要插入单个元素,则在发生异常的情况下容器中不会有任何更改 (强烈保证)。

Otherwise, the container is guaranteed to end in a valid state (basic guarantee).
否则,保证容器以有效状态结束 (基本保证)。

If allocator_traits::construct is not supported with the appropriate arguments for the element constructions, or if an invalid position is specified, it causes undefined behavior.
如果元素构造的适当参数不支持 allocator_traits::construct,或者如果指定了无效位置,则会导致未定义的行为。

References

http://www.cplusplus.com/reference/map/map/insert/

发布了443 篇原创文章 · 获赞 1685 · 访问量 101万+

猜你喜欢

转载自blog.csdn.net/chengyq116/article/details/104229191