C++的swap是非常重要的函数,尤其是在含有指针的类成员时,能提高效率。因此,对3种可能的swap编写方式作出总结,供必要的时候参考。
Article25.h文件及CPP文件
#ifndef ARTICLE25_H_
#define ARTICLE25_H_
#include <vector>
#include <typeinfo>
#include <iostream>
namespace Article25{
class WidgetImpl {
public:
explicit WidgetImpl(int i1, int i2, int i3, const std::vector<double> &v1) : a(i1), b(i2), c(i3), v(v1){}
const int get_a() const{
return a;
}
const int get_b() const{
return b;
}
const int get_c() const{
return c;
}
const std::vector<double>& get_v() const{
return v;
}
private:
int a, b, c;
std::vector<double> v;
};
class Widget{
// friend void swap(Widget &lhs, Widget &rhs); //第1种使用友元函数调用(注意:当且仅当需要在友元函数中访问类内部成员时,才建议使用友元函数)
public:
explicit Widget(int i1, int i2, int i3, const std::vector<double> &v1): pImpl(new WidgetImpl(i1, i2, i3, v1)),
use_count(new int(1)){}
Widget(const Widget& rhs): pImpl(new WidgetImpl(rhs.pImpl->get_a(), rhs.pImpl->get_b(), rhs.pImpl->get_c()
, rhs.pImpl->get_v())), use_count(new int(1)){}
Widget(Widget&& rhs): pImpl(std::move(rhs.pImpl)), use_count(std::move(rhs.use_count)){}
Widget& operator=(const Widget& rhs){
if(this != &rhs){
free();
++*rhs.use_count;
pImpl = rhs.pImpl;
use_count = rhs.use_count;
}
return *this;
}
Widget& operator=(Widget &&rhs){
if(this != &rhs){
free();
pImpl = std::move(rhs.pImpl);
use_count = std::move(rhs.use_count);
}
return *this;
}
~Widget(){
free();
}
void swap(Widget& rhs){
using std::swap;
swap(pImpl, rhs.pImpl);
swap(use_count, rhs.use_count);
}
private:
WidgetImpl* pImpl;
int *use_count;
void free(){
if(--*use_count == 0){
delete pImpl;
delete use_count;
}
}
};
//extern void swap(Widget &lhs, Widget &rhs); //第2种方式,在命名空间Article25中定义访问函数,由于受到作用域限制,必须在类中需要一个public的成员swap函数。
}
Article25.cpp文件
-----------------------------------------------
#include "Article25.h"
namespace Article25{
//void swap(Widget &lhs, Widget &rhs){
// lhs.swap(rhs);
//}
}
#endif /* ARTICLE25_H_ */
-------------------------------------------------------------------------
main.cpp文件
#include <iostream>
#include "Article25.h"
//第3种方式,在std命名空间中定义一个swap的模版函数特例,供其它函数调用,调用的原则是C++特例化及参数匹配调用。
namespace std{
template<>
void swap<Article25::Widget>(Article25::Widget &a, Article25::Widget &b){
a.swap(b);
}
}
int main() {
Article25::Widget wi1(1, 2, 3, std::vector<double>({1.0, 2.0, 3.0}));
Article25::Widget wi2(4, 5, 6, std::vector<double>({4.0, 5.0, 6.0}));
Article25::Widget wi3(7, 8, 9, std::vector<double>({7.0, 8.0, 9.0}));
wi1 = std::move(wi3);
using std::swap;
swap(wi1, wi2);
return 0;
}