std::vector 构造函数
std::vector
类可以通过多种不同的方式构造。使用右上角的按钮,方便地使用箭头导航。
std::vector
是一个 类模板,具有以下类型参数,这些参数在构造函数中使用
公共 | T | 元素类型 |
公共 | 分配器 | 分配器 类型,用于分配内部存储 |
默认构造函数
- C++20
- C++17
- C++17 之前
- 简化
- 详细
// 1)
vector()
: vector( Allocator() )
{
}
// 2)
explicit vector( Allocator const& alloc );
- 如果
Allocator
的构造函数也是noexcept
,则构造函数 1) 是noexcept
- 构造函数 2) 是
noexcept
,因为Allocator
之前已构造 - 两个构造函数都是
constexpr
// 1)
constexpr vector() noexcept(noexcept( Allocator() ))
: vector( Allocator() )
{
}
// 2)
explicit constexpr vector( Allocator const& alloc ) noexcept;
- 简化
- 详细
// 1)
vector()
: vector( Allocator() )
{
}
// 2)
explicit vector( Allocator const& alloc );
- 如果
Allocator
的构造函数也是noexcept
,则构造函数 1) 是noexcept
- 构造函数 2) 是
noexcept
,因为Allocator
之前已构造
// 1)
vector() noexcept(noexcept( Allocator() ))
: vector( Allocator() )
{
}
// 2)
explicit vector( Allocator const& alloc ) noexcept;
vector();
explicit vector( Allocator const& alloc );
默认构造函数。构造一个空容器。如果未提供分配器,则从默认构造的实例中获取分配器。
复杂度
常数。
示例
#include <iostream>
#include <vector>
int main() {
// Default constructed vector<int>:
std::vector<int> v;
std::cout << "v.size(): " << v.size();
}
v.size(): 0
重复值构造函数
- C++20
- 直到 C++20
- 直到 C++11
// prism-push-types:size_type
constexpr vector(
size_type count,
T const& value,
Allocator const& alloc = Allocator()
);
// prism-push-types:size_type
vector(
size_type count,
T const& value,
Allocator const& alloc = Allocator()
);
// prism-push-types:size_type
vector(
size_type count,
T const& value = T(),
Allocator const& alloc = Allocator()
);
使用 value
的 count
份副本构造向量。
复杂度
与 count
成线性关系。
示例
#include <iostream>
#include <vector>
int main() {
std::vector<int> v(4, 15);
for (auto elem : v)
std::cout << elem << ' ';
}
15 15 15 15
count
默认元素构造函数
- C++20
- 自 C++14 起
- 自 C++11 起
// prism-push-types:size_type
constexpr explicit vector(
size_type count,
Allocator const& alloc = Allocator()
);
// prism-push-types:size_type
explicit vector(
size_type count,
Allocator const& alloc = Allocator()
);
// prism-push-types:size_type
explicit vector( size_type count );
使用 count
个默认插入的 T
类型元素构造向量。不进行复制。
复杂度
与 count
成线性关系。
示例
#include <iostream>
#include <vector>
int main() {
// |0,0,0,0|
auto vec = std::vector<int>(4);
// |0,0,0,0,13|
vec.push_back(13);
for (auto elem : vec)
std::cout << elem << ' ';
}
0 0 0 0 13
基于范围的构造函数
- C++20
- 直到 C++20
template <typename InputIt>
constexpr vector(
InputIt first,
InputIt last,
Allocator const& alloc = Allocator()
);
template <typename InputIt>
vector(
InputIt first,
InputIt last,
Allocator const& alloc = Allocator()
);
使用范围 [first
, last
) 的内容构造容器。
重载决议
复杂度
给定 first
和 last
之间的距离为 N
- 如果
first
和last
都是 前向、双向或随机访问迭代器,则T
的复制构造函数仅被调用N
次,并且不会发生重新分配。 - 否则(
first
和last
只是 输入迭代器),T
的复制构造函数被调用O(N)
次,并且重新分配发生O(log N)
次。
示例
#include <iostream>
#include <vector>
int main() {
char buf[] = "Hello, World";
auto vec = std::vector<char>(
std::begin(buf),
std::next(std::begin(buf), 5)
);
for (auto elem : vec)
std::cout << elem << ' ';
}
H e l l o
复制构造函数
- C++20
- 直到 C++20
// (1)
constexpr vector( vector const& other );
// (2)
constexpr vector(
vector const& other,
Allocator const& alloc
);
// (1)
vector( vector const& other );
// (2)
vector(
vector const& other,
Allocator const& alloc
);
复制构造函数。使用 other
内容的副本构造容器。第二个版本使用 alloc
作为分配器。
获取分配器和推导
- 自 C++11 起
- 自 C++23 起
分配器通过调用如下方式获得
std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.get_allocator())
Allocator
仅在使用类模板参数推导时从第一个参数推导.复杂度
与 other
的大小呈线性关系。
示例
#include <iostream>
#include <vector>
int main() {
// ⚠ using C++17 CTAD
auto vec = std::vector{5, 21, 37, 11};
auto copied = std::vector(vec);
copied[2] = 38;
for (auto elem: vec) std::cout << elem << ' ';
std::cout << '\n';
for (auto elem: copied) std::cout << elem << ' ';
}
5 21 37 11
5 21 38 11
移动构造函数
- C++20
- 自 C++17 起
- 自 C++11 起
// 1)
constexpr vector( vector&& other ) noexcept;
// 2)
constexpr vector(
vector&& other,
Allocator const& alloc
);
// 1)
vector( vector&& other ) noexcept;
// 2)
vector(
vector&& other,
Allocator const& alloc
);
// 1)
vector( vector&& other );
// 2)
vector(
vector&& other,
Allocator const& alloc
);
移动构造函数。使用移动语义构造具有 other
内容的容器。分配器通过从属于 other
的分配器进行移动构造获得。移动后,other
保证是empty()
。
第二个重载接受一个用于构造容器的分配器,从 other
移动内容。如果 alloc != other.get_allocator()
,这将导致逐元素移动(在这种情况下,移动后 other
不保证是 empty()
)。
分配器推导
模板参数 Allocator
仅在使用类模板参数推导时从第一个参数推导
复杂度
如果 alloc != other.get_allocator()
则呈线性关系,否则为常数。
示例
#include <iostream>
#include <vector>
#include <iomanip>
int main() {
auto prev = std::vector{15, 3, 8};
auto current = std::vector( std::move(prev) );
std::cout << "prev.empty(): " << std::boolalpha << prev.empty() << '\n';
std::cout << "current: ";
for (auto elem: current)
std::cout << elem << ' ';
}
prev.empty(): true
15 3 8
初始化列表构造函数
- C++20
- 自 C++11 起
constexpr vector(
std::initializer_list<T> init,
Allocator const& alloc = Allocator()
);
vector(
std::initializer_list<T> init,
Allocator const& alloc = Allocator()
);
使用初始化列表 init
的内容构造容器。
此重载的存在意味着列表初始化和直接初始化做不同的事情
std::vector<int> b{3}; // creates a 1-element vector holding {3}
std::vector<int> a(3); // creates a 3-element vector holding {0, 0, 0}
std::vector<int> d{1, 2}; // creates a 2-element vector holding {1, 2}
std::vector<int> c(1, 2); // creates a 1-element vector holding {2}
复杂度
与 init
的大小呈线性关系。
示例
#include <iostream>
#include <vector>
int main() {
std::vector<int> v = { 14, 30, 18 };
for (auto elem : v)
std::cout << elem << ' ';
}
14 30 18