std重要库函数

std::exchange

std::exchage未出现之前, 我们交换两个变量的值,需要先定义一个临时的中间变量,这是经典老方法了。但是std::exchange让我们优雅地解决这个问题。

它的主要作用是替换一个对象的值,并返回该对象的旧值。这个函数在 C++14 中引入,主要用于简化和优化代码。原型是

1
2
template< class T, class U = T >
T exchange( T& obj, U&& new_value );

在C++ 20里给函数加上了constexpr

1
2
3
4
std::string name = "Alice";
std::string new_name = "Bob";

std::string old_name = std::exchange(name, new_name);

还可以用于容器

1
2
3
4
5
6
7
std::vector<int> v;
std::exchange(v, {1,2,3,4});
cout << v.size() << endl;
for (auto a : v)
{
cout << a << " ";
}

std::exchange在处理移动语义时非常有用。

std::exchange是原子操作的,所以在多线程环境下是安全的,如果对程序性能有严格要求,可以换std::swap或临时变量的方式。

std::transform

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
int multiply(int num)
{
return 3*num;
}

vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);

for(const auto &it: vec)
{
cout << it << endl;
}

// 将 vec 元素范围 ( 起始迭代器 和 末尾迭代器 ) 作为输入容器 , 将 vec 的起始迭代器作为输出容器起始点 , 也就是将输入容器的元素进行修改, 再次放回到该容器
std::transform(vec.begin(), vec.end(), vec.begin(), multiply );

for(const auto &it: vec)
{
cout << it << endl;
}

// 使用lambda表达式作为转换方式,如果输出容器的起始点改为 vec.end(),vec不会有变化
std::transform(vec.begin(), vec.end(), vec.begin(), [](int num){return 2*num; } );

for(const auto &it: vec)
{
cout << it << endl;
}

再看一个配合std::back_inserter使用的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
vector<int>  vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);

vector<int> new_vec;
std::transform(vec.begin(), vec.end(), std::back_inserter(new_vec), [](int v){ return 3*v; } );

cout << "new vec size: " << new_vec.size() << endl;
for(auto it : new_vec)
{
cout << it << " ";
}

运行结果
1
2
new vec size: 5
3 6 9 12 15