您的位置:首页 > 其它

谷歌LevelDB之源码分析之1______Slice封装

2016-04-10 20:12 344 查看

Slice

<span style="font-size:18px;">先贴代码,自己根据源码手动敲了一遍,增加点感觉.	</span>
<span style="font-size:18px;">
</span>
<span style="font-size:18px;">#include <string>
#include <assert.h>
namespace google
{
class Slice
{
public:
Slice() :data_(""), size_(0) {};
Slice(const char*d, size_t s) :data_(d), size_(s) {}
Slice(const std::string&s) :data_(s.data()), size_(s.size()) {}
Slice(const char*d) :data_(d), size_(strlen(d)) {}
~Slice()
{

}
public:
const char* data()const
{
return data_;
}
size_t size()const
{
return size_;
}
bool empty()const
{
return size_ == 0;
}
char operator[](size_t n)const
{
assert(n < size_);
return data_
;
}
void clear()
{
data_ = "";
size_ = 0;
}
void remove_prefix(size_t n)
{
assert(n < size_);
data_ += n;
size_ -= n;
}
std::string toString()const
{
return std::string(data_, size_);
}
int compare(const Slice&b)const;
bool starts_with(const Slice&x)const
{
return ((size_ >= x.size_) && (memcmp(data_, x.data_, x.size_) == 0));
}
private:
const char* data_;
size_t size_;
};

inline bool operator==(const Slice&x, const Slice&y)
{
return ((x.size() == y.size()) && (memcmp(x.data(), y.data(), x.size() == 0)));
}

inline bool operator!=(const Slice&x, const Slice&y)
{
return !(x == y);
}

int Slice::compare(const Slice&b)const
{
const int min_len = (size_ < b.size_) ? size_ : b.size_;

int r = memcmp(data_, b.data_, min_len);

if (0 == r)
{
if (size_ < b.size_)
{
r = -1;
}
else if (size_ > b.size_)
{
r = +1;
}
}

return r;
}
}

源码中Slice该数据结构广泛使用,其简洁的封装而又完美的封装体现谷歌代码之简洁美而又不失效率之特点。</span>
<span style="font-size:18px;">
1.该类之封装了2个数据成员:char*和非负整型;</span>
<span style="font-size:18px;">2.在c++中,若类具有个单参数的构造函数,比如:Slice(const std::string&s)和Slice(const char*d)则可以进行类型的隐式转换</span>
<span style="font-size:18px;">例如:定义函数void fun(const Slice&);</span>
<span style="font-size:18px;">变量:	string str;</span>
<span style="font-size:18px;">	char* pch = "hello,world";</span>
<span style="font-size:18px;">则可以使用fun(str)及fun(pch)对fun的调用:其中string与char*均隐式转换成了Slice类型;</span>
<span style="font-size:18px;">在c++primer第四版中,曾提出避免这类隐式转换,若需要可以采用显式转换的方式:如fun(Slice(str))及fun(Slice(pch));</span>
<span style="font-size:18px;">在c++中,采用关键字explicit修饰单参数构造函数以避免类型的隐式转换:例 explicit  Slice(const std::string&s);则必须使用fun(Slice(str))进行fun函数的调用;</span>
<span style="font-size:18px;">在此处,因为对于leveldb要进行大量的put,get数据操作,则谷歌使用了隐式类型转换。</span>
<span style="font-size:18px;">3.运算符重载:对于2个Slice类型的比较,实质是两个常量字符串的比较,这类问题在面试中经常遇到,在此处,谷歌使用内存比较的方式处理:首先获取2个字符串之间的最小长度,然后调用memcmp函数进行比较。</span>
<span style="font-size:18px;">注:int memcmp(const void *buf1, const void *buf2, unsigned int count);</span>
<span style="font-size:18px;">int memcmp(const void *buf1, const void *buf2, unsigned int count);</span>
<span style="font-size:18px;">使用该算法效率很高,比常见的字符循环比较效率要高出甚多。</span>
<span style="font-size:18px;">在此处,先重载==运算符,再调用==重载!=运算符。</span>
<span style="font-size:18px;">4.这段代码及其简单,但是具有很多其他细节值得我们去学习:</span>
<span style="font-size:18px;">1》内联函数的使用;</span>
<span style="font-size:18px;">2》const的使用;</span>
<span style="font-size:18px;">3》关系表达式的简洁写法;</span>
<span style="font-size:18px;">4》assert断言的合理使用;</span>
<span style="font-size:18px;">5》尽量使用库函数,少自己实现算法,毕竟自己手动写的算法不如经过工业考验的库函数效率高,例memcmp的使用。</span>
<span style="font-size:18px;">

</span>

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: