utility是一个实用组件库,里面包括一些非常有用的函数,比如swap,move,forwardexchange等,这篇学习这些函数的基本使用。
交换两个对象的值 (函数模板) | |
(C++14) | 将实参替换为一个新值,并返回其先前值 (函数模板) |
(C++11) | 转发一个函数实参 (函数模板) |
(C++11) | 获得右值引用 (函数模板) |
(C++11) | 若移动构造函数不抛出则获得右值引用 (函数模板) |
(C++17) | 获得到其实参的 const 引用 (函数模板) |
(C++11) | 获取到其实参的引用,用于不求值语境中 (函数模板) |
1.swap交换两个对象的值,示例:
#include <iostream>
#include <string>
#include <utility>
using namespace std;
class Yak {
public:
Yak(string name = "", int h = 0, int w = 0):
m_name(name),
m_height(h),
m_weight(w)
{
cout << "constructe============== " << this << " name= " << name << " height= " << h << " weight= " << w << endl;
}
~Yak(){ cout << "destructe~~~~~~~~~~~~~~~ " << this << " name= " << this->m_name << " height= " << m_height << " weight= " << m_weight << endl;}
string m_name{""};
int m_height{0};
int m_weight{0};
};
int main()
{
Yak yak1;
yak1.m_name = "yak1";
yak1.m_height = 10001;
yak1.m_weight = 201;
Yak yak2;
yak2.m_name = "yak2";
yak2.m_height = 10002;
yak2.m_weight = 202;
cout << "Yak1.name= " << yak1.m_name << " Yak2.name= " << yak2.m_name << " yak1 = " << &yak1 << " yak2= " << &yak2 << endl;
cout << "============swap=============" << endl;
std::swap(yak1, yak2);
cout << "Yak1.name= " << yak1.m_name << " Yak2.name= " << yak2.m_name << " yak1 = " << &yak1 << " yak2= " << &yak2 << endl;
cout << "Hello World!" << endl;
return 0;
}
运行结果:
从运行结果看:交换的时候多了一个析构函数,产生了一个临时对像了吗
原来原码里的实现有T c(std::move(a)); a=std::move(b); b=std::move(c); 从这段原码可以看出交换时会产生一个临时对像c.
2.move
用于指示对象 t
可以“被移动”,即允许从 t
到另一对象的有效率的资源传递。特别是, std::move
生成标识其参数 t
的亡值表达式。它准确地等价于到右值引用类型的 static_cast 。
示例:
#include <iostream>
#include <string>
#include <vector>
#include <utility>
using namespace std;
int main()
{
string str = "Yak is mao niu";
vector<std::string> vecStr;
// 使用 push_back(const T&) 重载,
// 表示我们将带来复制 str 的成本
vecStr.push_back(str);
std::cout << "After copy, str is \"" << str << "\"\n";
// 使用右值引用 push_back(T&&) 重载,
// 表示不复制字符串;而是
// str 的内容被移动进 vector
// 这个开销比较低,但也意味着 str 现在可能为空。
vecStr.push_back(std::move(str));
std::cout << "After move, str is \"" << str << "\"\n";
std::cout << "The contents of the vector are \"" << vecStr[0]
<< "\", \"" << vecStr[1] << "\"\n";
cout << "Hello World!" << endl;
return 0;
}
从上面的结果看,move值之后原str内容被清空了。
下面用一个类来演示它的值:
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <utility>
using namespace std;
class Yak {
public:
Yak(string name = "", int h = 0, int w = 0):
m_name(name),
m_height(h),
m_weight(w)
{
cout << "constructe============== " << this << " name= " << name << " height= " << h << " weight= " << w << endl;
}
~Yak(){ cout << "destructe~~~~~~~~~~~~~~~ " << this << " name= " << this->m_name << " height= " << m_height << " weight= " << m_weight << endl;}
string m_name{""};
int m_height{0};
int m_weight{0};
};
int main()
{
Yak yak1;
yak1.m_name = "yak1";
yak1.m_height = 10001;
yak1.m_weight = 201;
Yak yak2;
yak2.m_name = "yak2";
yak2.m_height = 10002;
yak2.m_weight = 202;
vector<Yak> vec;
vec.reserve(16); //防止数据添加时重新分配
vec.push_back(yak1);
cout << "Yak2.name= " << yak2.m_name << " Yak2.height= " << yak2.m_height << " yak2.weight = " << yak2.m_weight << endl;
vec.push_back(std::move(yak2));
cout << "Yak2.name= " << yak2.m_name << " Yak2.height= " << yak2.m_height << " yak2.weight = " << yak2.m_weight << endl;
cout << "Hello World!" << endl;
return 0;
}
运行结果:
为什么move之后Yak2的对象的值没有被清空呢???
参考: