Boost源码简析系列——Array(2)
1. 赋值函数等
//...
static size_type size() { return N; }
static bool empty() { return false; }
static size_type max_size() { return N; }
enum { static_size = N };
void swap (array<T,N>& y) {
std::swap_ranges(begin(),end(),y.begin());
}
const T* data() const { return elems; }
template <typename T2>
array<T,N>& operator= (const array<T2,N>& rhs) {
std::copy(rhs.begin(),rhs.end(), begin());
return *this;
}
void assign (const T& value)
{
std::fill_n(begin(),size(),value);
}
private:
static void rangecheck (size_type i) {
if (i >= size()) { throw std::range_error("array"); }
}
//...
size()
array容器能容元素的数量。
empty()
容器是否为空???
max_size()
容器最多能容元素的数量。
swap()
交换两个容器元素序列中的相应元素。
data()
返回容器中存放元素的数组首地址。
operator=()
重载赋值函数。
assign()
用一个值取代一段元素序列中元素的值。
rangecheck()
检查是否超范围访问容器。
在这一组函数中,有几个问题我不知道代码的编写者是怎么想的。
首先是,既然boost::array是静态数组的代替,那么对于定义好的boost::array对象能存放的元素个数也就定下来,不能修改,那么在这里就没有必要提供两个member function:
size()和max_size()。何况这两个函数除了名字不同以外,其他的操作都是一样的。也许Josuttis是给以后这个类的扩展预留了空间吧。
其次是,empty()函数也让人浮想联翩,看起来好像是判断容器是否为空的方法,但是仔细一看实现代码,却是直接返回了一个false。
然后是,data(),居然直接返回的是容器中第一个元素的地址。我想,用户用指针直接访问元素并不是Josuttis愿意看到的。
最后是,rangecheck()函数,对是否访问位置溢出的检查,只注意了上溢,没有注意到有可能下溢。
我在这里并不是指责Josuttis没有程序员应用的严谨,这些看似有漏洞的地方,是作者为了以后扩展功能故意留下的。
剩下的三个函数,都是赋值函数:
swap(),把A容器中的全部元素与B容器中的相应位置的元素相互交换。A是调用swap()函数。用了STL中标准算法swap_ranges()。
operator=(),用B容器给A容器赋值,A容器调用operator=()函数。
assign(),用一个指定的值代替容器中一段元素序列中的元素的值。用了标准算法fill_n()。
这组函数使用,见例2。
2. 比较函数
//...
template<class T, std::size_t N>
bool operator== (const array<T,N>& x, const array<T,N>& y) {
return std::equal(x.begin(), x.end(), y.begin());
}
template<class T, std::size_t N>
bool operator< (const array<T,N>& x, const array<T,N>& y) {
return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
}
template<class T, std::size_t N>
bool operator!= (const array<T,N>& x, const array<T,N>& y) {
return !(x==y);
}
template<class T, std::size_t N>
bool operator> (const array<T,N>& x, const array<T,N>& y) {
return y<x;
}
template<class T, std::size_t N>
bool operator<= (const array<T,N>& x, const array<T,N>& y) {
return !(y<x);
}
template<class T, std::size_t N>
bool operator>= (const array<T,N>& x, const array<T,N>& y) {
return !(x<y);
}
template<class T, std::size_t N>
inline void swap (array<T,N>& x, array<T,N>& y) {
x.swap(y);
}
//...
operator==()
比较两个容器中元素序列是否相等。
operator<()
比较两个容器中元素序列按字典排序哪个小。
operator!=()
判断两个容器中元素序列是否不等。
operator>()
比较两个容器中元素序列按字典排序哪个大。
operator<=()
比较两个容器,前者是否小于等于后者。
operator>=()
比较两个容器,前者是否大于等于后者。
swap()
用static的形式提供了swap的功能。
这组比较函数,是基于C++标准库的标准算法做出的。
operator==()中为了比较两个序列中相应元素是否相等,用了标准算法中的equal()。如果两个序列对应元素相同则真。
operator<()中为了比较两个序列按字典序谁大谁小,前者小为真。用了lexicograhpic_compare()。
其他的函数,又是基于==和<很简单就做出来了。实际的使用,参考例2。
上面就是,boost::array提供给我们的所有资源及其源码。从这些源码我们可以看出来,技术上是依赖了C++的标准库算法。
提供给了用户大多数的STL容器接口,让用户可以很方便的访问,比较容器中的元素。通过at()访问元素还可以避免超范围访问。
从效率上来看,几乎所有的member function的实现都非常简单,编译器把她们都看成是inline函数,比起普通数组来说,效率并没有下降。
所以总的说来,这个boost::array是优秀的静态数组容器类。完全可以作为普通数组的替代。下面两个例子,具体实现了对array类的使用方式。
//例2
#include <iostream>
#include <string>
#include <boost/array.hpp>
#include <stdlib.h>
int main(void)
{
boost::array<std::string,4> seasons = {
{ "spring", "summer", "autumn", "winter" }
};
std::cout<<seasons[2]<<'\n';
std::cout<<seasons.at(2)<<'\n';
std::cout<<seasons.front()<<'\n';
std::cout<<seasons.back()<<'\n';
std::cout<<seasons.size()<<'\n';
std::cout<<seasons.max_size()<<'\n';
boost::array<std::string,4> _seasons = {
{ "spring", "summer", "autumn"}};
if(seasons == _seasons)
{
std::cout<<"equality."<<'\n';
}
else if(_seasons < seasons)
{
std::cout<<"_seasons is more smaller."<<'\n';
}
else
{
std::cout<<"seasons is more smaller."<<'\n';
}
system("pause");
return 0;
}
同例1一样,例2也在Dev-C++上编译通过,而vc告诉我有语法错误,我晕。
参考文献:
boost::array英文文档;
Bjarne Stroustrup 《The C++ Programming Language,3rd edition》。
sixsavage(野人)于March 22, 2004作
本文地址:http://com.8s8s.com/it/it28941.htm