以下实现了C++标准模板库std::vector的部分实现,参考了 cplusplus.
关于C++中标准模板库std::vector的介绍和用法可以参考 https://blog.csdn.net/fengbingchun/article/details/51510916
实现代码vector.hpp内容如下:
#ifndef FBC_STL_VECTOR_HPP_
#define FBC_STL_VECTOR_HPP_
#include
namespace fbcstd {
template
class vector {
public:
typedef size_t size_type;
typedef T value_type;
typedef T* iterator;
typedef const T* const_iterator;
vector();
vector(size_type n, const value_type& val = value_type());
vector(const vector& x);
~vector();
void reserve(size_type n);
size_type capacity() const;
size_type size() const;
bool empty() const;
value_type* data();
const value_type* data() const;
value_type& at(size_type n);
const value_type& at(size_type n) const;
value_type& operator [] (size_type n);
const value_type& operator [] (size_type n) const;
vector& operator = (const vector& x);
void clear();
value_type& back();
const value_type& back() const;
value_type& front();
const value_type& front() const;
void push_back(const value_type& val);
void pop_back();
void resize(size_type n, value_type val = value_type());
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
private:
size_type size_ = 0;
size_type capacity_ = 0; // 2^n
value_type* buffer_ = nullptr;
}; // class vector
template inline
vector::vector() : size_(0), capacity_(0), buffer_(nullptr)
{
}
template inline
vector::vector(size_type n, const value_type& val)
{
reserve(n);
size_ = n;
for (size_t i = 0; i < n; ++i)
buffer_[i] = val;
}
template inline
vector::vector(const vector& x)
{
reserve(x.size_);
size_ = x.size_;
for (size_t i = 0; i < x.size_; ++i)
buffer_[i] = x.buffer_[i];
}
template inline
vector::~vector()
{
if (buffer_)
delete [] buffer_;
}
template inline
void vector::reserve(size_type n)
{
if (capacity_ < n) {
delete [] buffer_;
capacity_ = 1;
if (capacity_ < n) {
capacity_ = 2;
while (capacity_ < n) {
capacity_ *= 2;
}
}
buffer_ = new value_type[capacity_];
}
}
template inline
size_t vector::capacity() const
{
return capacity_;
}
template inline
size_t vector::size() const
{
return size_;
}
template inline
bool vector::empty() const
{
return size_ == 0 ? true : false;
}
template inline
T* vector::data()
{
return buffer_;
}
template inline
const T* vector::data() const
{
return buffer_;
}
template inline
T& vector::at(size_type n)
{
if (size_ <= n) abort();
return buffer_[n];
}
template inline
const T& vector::at(size_type n) const
{
if (size_ <= n) abort();
return buffer_[n];
}
template inline
T& vector::operator [] (size_type n)
{
if (size_ <= n) abort();
return buffer_[n];
}
template inline
const T& vector::operator [] (size_type n) const
{
if (size_ <= n) abort();
return buffer_[n];
}
template inline
vector& vector::operator = (const vector& x)
{
reserve(x.size_);
size_ = x.size_;
for (size_t i = 0; i < size_; ++i)
buffer_[i] = x.buffer_[i];
return *this;
}
template inline
void vector::clear()
{
size_ = 0;
}
template inline
T& vector::back()
{
if (size_ == 0) abort();
return buffer_[size_-1];
}
template inline
const T& vector::back() const
{
if (size_ == 0) abort();
return buffer_[size_-1];
}
template inline
T& vector::front()
{
if (size_ == 0) abort();
return buffer_[0];
}
template inline
const T& vector::front() const
{
if (size_ == 0) abort();
return buffer_[0];
}
template inline
void vector::push_back(const value_type& val)
{
if (size_ >= capacity_) {
T* tmp = new T[size_];
for (size_t i = 0; i < size_; ++i)
tmp[i] = buffer_[i];
reserve(size_+1);
for (size_t i = 0; i < size_; ++i)
buffer_[i] = tmp[i];
delete [] tmp;
}
buffer_[size_] = val;
size_ += 1;
}
template inline
void vector::pop_back()
{
if (size_ == 0) abort();
--size_;
}
template inline
void vector::resize(size_type n, value_type val)
{
if (size_ < n) {
if (n > capacity_) {
T* tmp = new T[size_];
for (size_t i = 0; i < size_; ++i)
tmp[i] = buffer_[i];
reserve(n);
for (size_t i = 0; i < size_; ++i)
buffer_[i] = tmp[i];
delete [] tmp;
}
for (size_t i = size_; i < n; ++i)
buffer_[i] = val;
}
size_ = n;
}
template inline
T* vector::begin()
{
return buffer_;
}
template inline
const T* vector::begin() const
{
return buffer_;
}
template inline
T* vector::end()
{
return buffer_ + size_;
}
template inline
const T* vector::end() const
{
return buffer_ + size_;
}
template static inline
bool operator == (const vector& lhs, const vector& rhs)
{
if (lhs.size() != rhs.size())
return false;
for (size_t i = 0; i < lhs.size(); ++i) {
if (lhs[i] != rhs[i])
return false;
}
return true;
}
template static inline
bool operator != (const vector& lhs, const vector& rhs)
{
return !(lhs == rhs);
}
template static inline
bool operator < (const vector& lhs, const vector& rhs)
{
bool flag = true;
if (lhs.size() == rhs.size()) {
if (lhs == rhs) {
flag = false;
} else {
for (size_t i = 0; i < lhs.size(); ++i) {
if (lhs[i] > rhs[i]) {
flag = false;
break;
}
}
}
} else if (lhs.size() < rhs.size()) {
vector vec(lhs.size());
for (size_t i = 0; i < lhs.size(); ++i)
vec[i] = rhs[i];
if (lhs == vec) {
flag = true;
} else {
for (size_t i = 0; i < lhs.size(); ++i) {
if (lhs[i] > rhs[i]) {
flag = false;
break;
}
}
}
} else {
vector vec(rhs.size());
for (size_t i = 0; i < rhs.size(); ++i)
vec[i] = lhs[i];
if (vec == rhs) {
flag = false;
} else {
for (size_t i = 0; i < rhs.size(); ++i) {
if (lhs[i] > rhs[i]) {
flag = false;
break;
}
}
}
}
return flag;
}
template static inline
bool operator <= (const vector& lhs, const vector& rhs)
{
return !(rhs < lhs);
}
template static inline
bool operator > (const vector& lhs, const vector& rhs)
{
return (rhs < lhs);
}
template static inline
bool operator >= (const vector& lhs, const vector& rhs)
{
return !(lhs < rhs);
}
} // namespace fbcstd
#endif // FBC_STL_VECTOR_HPP_
测试代码test_vector.cpp内容如下:
#include
#include "vector.hpp"
#include "string.hpp"
#define std fbcstd
int main()
{
{ // constructor, capacity, size, empty, data
std::vector vec1;
fprintf(stdout, "vec1 size: %d, capacity: %d, empty: %d\n", vec1.size(), vec1.capacity(), vec1.empty());
std::vector vec2(1);
fprintf(stdout, "vec2 size: %d, capacity: %d, empty: %d\n", vec2.size(), vec2.capacity(), vec2.empty());
fprintf(stdout, "vec2 data: %d\n", *(vec2.data()));
std::vector vec3(5, "test vector");
fprintf(stdout, "vec3 size: %d, capacity: %d, empty: %d\n", vec3.size(), vec3.capacity(), vec3.empty());
const std::string* p1 = vec3.data();
fprintf(stdout, "vec3 data: \n");
for (size_t i = 0; i < vec3.size(); ++i) {
fprintf(stdout, " %s,", (*p1).c_str());
p1++;
}
std::vector vec4(vec3);
fprintf(stdout, "\nvec4 size: %d, capacity: %d, empty: %d\n", vec4.size(), vec4.capacity(), vec4.empty());
std::string* p2 = vec4.data();
fprintf(stdout, "vec4 data: \n");
for (size_t i = 0; i < vec4.size(); ++i)
*p2++ = "TEST VECTOR";
const std::string* p3 = vec4.data();
for (size_t i = 0; i < vec4.size(); ++i) {
fprintf(stdout, " %s,", (*p3).c_str());
p3++;
}
fprintf(stdout, "\n");
}
{ // at, [], =, clear
std::vector vec1(2);
vec1.at(0) = "test";
vec1.at(1) = "vector";
fprintf(stdout, "vec1: %s, %s\n", vec1.at(0).c_str(), vec1.at(1).c_str());
vec1[0] = "TEST";
vec1[1] = "VECTOR";
fprintf(stdout, "vec1: %s, %s\n", vec1[0].c_str(), vec1[1].c_str());
std::vector vec2;
vec2 = vec1;
fprintf(stdout, "vec2 size: %d, %s, %s\n", vec2.size(), vec2[0].c_str(), vec2[1].c_str());
vec2.clear();
fprintf(stdout, "vec2 size: %d\n", vec2.size());
}
{ // back, front
std::vector vec(2, 1000);
fprintf(stdout, "value: %d\n", vec.back());
vec.back() = -1000;
fprintf(stdout, "value: %d\n", vec.back());
fprintf(stdout, "value: %d\n", vec.front());
vec.front() = -1000;
fprintf(stdout, "value: %d\n", vec.front());
}
{ // push_back, pop_back
std::vector vec;
for (int i = 0; i < 10; ++i)
vec.push_back((i+1)*10);
fprintf(stdout, "vec: size: %d, capacity: %d\nvalue: ", vec.size(), vec.capacity());
for (int i = 0; i < vec.size(); ++i)
fprintf(stdout, " %d,", vec[i]);
for (int i = 0; i < 5; ++i)
vec.pop_back();
fprintf(stdout, "\nvec: size: %d, capacity: %d\nvalue: ", vec.size(), vec.capacity());
for (int i = 0; i < vec.size(); ++i)
fprintf(stdout, " %d,", vec[i]);
fprintf(stdout, "\n");
}
{ // resize
std::vector myvector;
for (int i = 1; i < 10; ++i)
myvector.push_back(i);
myvector.resize(5);
myvector.resize(8,100);
myvector.resize(12);
fprintf(stdout, "myvector contains:");
for (size_t i = 0; i < myvector.size(); ++i)
fprintf(stdout, " %d,", myvector[i]);
fprintf(stdout, "\n");
}
{ // begin, end
std::vector myvector;
for (int i = 1; i <= 5; ++i)
myvector.push_back(i);
fprintf(stdout, "myvector contains:");
for (std::vector::iterator it = myvector.begin() ; it != myvector.end(); ++it)
fprintf(stdout, " %d,", *it);
fprintf(stdout, "\n");
for (std::vector::const_iterator it = myvector.begin() ; it != myvector.end(); ++it)
fprintf(stdout, " %d,", *it);
fprintf(stdout, "\n");
}
{ // compare operator
std::vector foo (3,100);
std::vector bar (2,200);
if (foo == bar) fprintf(stdout, "foo and bar are equal\n");
if (foo != bar) fprintf(stdout, "foo and bar are not equal\n");
if (foo < bar) fprintf(stdout, "foo is less than bar\n");
if (foo > bar) fprintf(stdout, "foo is greater than bar\n");
if (foo <= bar) fprintf(stdout, "foo is less than or equal to bar\n");
if (foo >=bar) fprintf(stdout, "foo is greater than or equal to bar\n");
}
return 0;
}
CMakeLists.txt内容如下:
PROJECT(Samples_STL_Implementation)
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall -O2 -std=c11")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -O2 -std=c++11")
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src)
MESSAGE(STATUS "project source dir: ${PROJECT_SOURCE_DIR}")
FILE(GLOB tests ${PROJECT_SOURCE_DIR}/test/*.cpp)
FOREACH (test ${tests})
STRING(REGEX MATCH "[^/]+$" test_file ${test})
STRING(REPLACE ".cpp" "" test_basename ${test_file})
ADD_EXECUTABLE(${test_basename} ${test})
TARGET_LINK_LIBRARIES(${test_basename} pthread)
ENDFOREACH()
build.sh脚本内容如下:
#! /bin/bash
real_path=$(realpath $0)
dir_name=`dirname "${real_path}"`
echo "real_path: ${real_path}, dir_name: ${dir_name}"
new_dir_name=${dir_name}/build
mkdir -p ${new_dir_name}
cd ${new_dir_name}
cmake ..
make
cd -
编译及执行操作步骤:将终端定位到Samples_STL_Implementation目录下,执行:$ ./build.sh , 然后再执行$ ./build/test_vector即可。
GitHub: https://github.com/fengbingchun/Linux_Code_Test