boost::swap 的实现原理

在 STL 已提供std::swap 时为什么还有必要使用 boost::swap

std::swap 的行为等效于:

 template <class T> void swap ( T& a, T& b )
{
  T c(a); 
  a=b; 
  b=c;
}

现在,对于存储大量数据的类,此方法可能不是交换数据的最有效方法,因为 swap 涉及到一个 copy construction 和两次赋值。另外,对于出于设计原因拥有 private 构造函数而没有复制构造函数的类,所以这种交换风格不适用。以下是 boost::swap 提供的功能:

  • 您可以交换 T 类型的数组,而 std::swap 不能。
  • boost::swap 可调用具有签名 swap(T&, T&) 的函数,只要存在相同的签名,且不存在默认的 copy constructor 及两个赋值选项。
  • boost::swap 可调用 std::swap 的一个特殊化模板。
  • 如果上面第二和第三个选项都是有效选项,T 必须是可构造和可赋值的副本。

清单 19 给出了用于交换两个数组的 boost::swap


清单 19. 使用 boost::swap 交换两个数组  
 				
#include <boost/swap.hpp>
#include <boost/foreach.hpp>
#include <iostream>
using namespace std;
 
int main()
{
  int a[] = {10, 20, 30, 40};
  int b[] = {4, 3, 2, 1};
 
  boost::swap(a, b); // using std::swap here won't work 
 
  BOOST_FOREACH(int t, a) { cout << t << endl; }
  BOOST_FOREACH(int t, a) { cout << t << endl; }
}

boost::swap 调用您的自定义交换例程的示例如 清单 20 中所示。


清单 20. 使用 boost::swap 实现自定义交换  
 				
#include <boost/swap.hpp>
#include <iostream>
using namespace std;
 
typedef struct T { 
  int m_data;
  T(int data) : m_data(data) { }
} T;
 
void swap(T& a, T& b) // custom swap routine that boost ::swap calls
{
  cout << "In custom swap" << endl;
  a.m_data ^= b.m_data;
  b.m_data ^= a.m_data;
  a.m_data ^= b.m_data;
}
 
int main()
{
  T a(30), b(10);
  boost::swap(a, b);
  cout << a.m_data << endl;
  cout << b.m_data << endl;
}

最后,模板特殊化的版本如 清单 21 中所示。


清单 21. 使用 std::swap 的模板特殊化版本  
 				
#include <boost/swap.hpp>
#include <iostream>
using namespace std;
 
typedef struct T { 
  int m_data;
  T(int data) : m_data(data) { }
} T;
 
namespace std { 
template<
void swap<T> (T& a, T& b) 
{
  cout << "In template-specialized swap" << endl;
  a.m_data ^= b.m_data;
  b.m_data ^= a.m_data;
  a.m_data ^= b.m_data;
}
}
 
int main()
{
  T a(30), b(10);
  boost::swap(a, b);
  cout << a.m_data << endl;
  cout << b.m_data << endl;
}

现在,让我们看看实现 boost::swap 的内部原理。我们感兴趣的是如何定义 swap...for 数组。清单 22 给出了代码,它从 boost/swap.hpp 复制而来。


清单 22. boost::swap 的源代码  
 				
#include <algorithm> //for std::swap
#include <cstddef> //for std::size_t

namespace boost_swap_impl
{
  template<class T>
  void swap_impl(T& left, T& right)
  {
    using namespace std;//use std::swap if argument dependent lookup fails
    swap(left,right);
  }

template<class T, std::size_t N>
  void swap_impl(T (& left)[N], T (& right)[N])
  {
    for (std::size_t i = 0; i < N; ++i)
    {
      ::boost_swap_impl::swap_impl(left[i], right[i]);
    }
  }
} 

namespace boost
{
  template<class T1, class T2>
  void swap(T1& left, T2& right)
  {
    ::boost_swap_impl::swap_impl(left, right);
  }
}

对于数组,调用 boost::swap 最终会导致调用 void swap_impl(T (& left)[N], T (& right)[N]),因为后者也已针对数组进行了特殊化处理。查看声明 swap_impl(T (& left)[N], T (& right)[N]),这里left 和 right 是具有类型 T 和大小 N 的数组的引用。两个数组必须具有相同的大小,否则您会获得编译错误消息。

对于所有其他情形,会调用 swap_impl(T& left, T& right)。查看 swap_impl(T& left, T& right) 的定义,您会看到它调用了 swap 例程。如果您拥有自己的模板特殊化的 std::swap 版本(请参见 清单 21)或全局 swap 例程(请参见 清单 20),将调用相同例程。否则,将调用 std::swap

如果 boost::swap 和 std::swap 位于相同范围内,那么对 swap 的调用将优先于 std::swap

原链接:http://www.oschina.net/question/129540_32439
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值