c++标准库源码学习笔记
Posted 胖虎code
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++标准库源码学习笔记相关的知识,希望对你有一定的参考价值。
目录
智能指针管理句柄类的资源释放
表达式和类型之typename
自制stl vector
iterator_traits实现::std::distance
enum class
智能指针管理句柄类的资源释放
#include <fcntl.h>
#include <unistd.h>
#include <cstdio>
#include <memory>
#include <errno.h>
#include <string.h>
int main(int argc, char ** argv)
{
int fd =::open(argv[1], O_RDONLY);
if( fd ==-1)
{printf("open failure:%s\n", strerror(errno)); return 1;}
::std::unique_ptr<int, void(*)(int*)> gurd\
(&fd,[](int*fd){::close(*fd);});
char buf[10];
ssize_t nread;
do{
nread =::read(fd, buf, sizeof(buf));
}
while(fd<0 && errno == EINTR);
if( nread <0)
{printf("read failure:%s\n", strerror(errno)); return 1;}
printf("%s\n", buf);
}
//编译$g++ -Wall -Wextra -std=c++11 src.cpp
核心代码:
template <class U, class D> unique_ptr (U* p, D del);自定义Deleter
任意类型的连接
#include <string>
#include <vector>
#include <iostream>
#include <list>
template<typename T>
typename T::value_type sum(const T & t)
{
typename T::value_type res ={};
for(const auto & a: t)
res+=a;
return res;
}
int main()
{
std::vector<int> vec = {1,2,3,4,5,6};
std::cout<<sum(vec)<<std::endl;
std::list<std::string> li ={"hello", "world"};
std::cout<<sum(li)<<std::endl;
return 0;
}
自制vector
#include <iostream>
#include <string>
#include <cstddef>
namespace my
{
template<typename ValueT>
class vector
{
public:
using value_type = ValueT;
using reference = ValueT&;
using const_reference = const ValueT;
using iterator = ValueT*;
using const_iterator =const ValueT*;
using size_type =::size_t;
using difference_type =::ptrdiff_t;
private:
ValueT * m_data;
::size_t m_size;
::size_t m_capacity;
public:
constexpr vector():m_data(),m_size(),m_capacity(){}
~vector()
{
//先析构,再释放内存
for(::size_t k =0; k <m_size; ++k)
m_data[k].~ValueT();
if( this->m_data)
::operator delete(this->m_data);
}
vector(const vector &rhs)
{
//allocate memory not call this's constructor
this->m_data=static_cast<ValueT*>(::operator new(\
rhs.m_capacity*sizeof(ValueT) ));
this->m_size = 0;
this->m_capacity = rhs.m_capacity;
//call this's constructor
try{
for(int k=0; k<rhs.m_size; ++k)
::new( &this->m_data[k])ValueT(rhs.m_data[k]),\
this->m_size+=1;
}
catch(...)
{
//first call destructor then call ::operator delete
for(int k=0; k <this->m_size; ++k)
this->m_data[k].~ValueT();
::operator delete(this->m_data);
}
}
vector(vector &&rhs)
{
this->m_capacity = rhs.m_capacity;
this->m_size = rhs.m_size;
this->m_data = rhs.m_data;
rhs.m_data = nullptr;
rhs.m_size = 0;
rhs.m_capacity = 0;
}
vector & operator=(const vector & rhs);
vector & operator =(vector && rhs)noexcept;
public:
//iterator
iterator begin()noexcept
{
return this->m_data;
}
const_iterator begin()const noexcept
{
return this->m_data;
}
iterator end() noexcept
{
return this->m_data +this->m_size;
}
const_iterator end()const noexcept
{
return this->m_data +this->m_size;
}
//accessor
ValueT * data()noexcept
{
return this->m_data;
}
const ValueT * data()const noexcept
{
return this->m_data;
}
size_type size()const noexcept
{
return this->m_size;
}
size_type capacity() const noexcept
{
return this->m_capacity;
}
bool empty()
{return this->m_size == 0;}
void clear()const noexcept
{
//clear only call the destructor not free the allocated memory
for(int k =0; k < this->m_size ; ++k)
this->m_data[k].~ValueT();
this->m_size = 0;
}
void pop_back()
{
assert(!this->empty());
size_type k = this->m_size -1;
this->m_data[k].~ValueT();
this->m_size-=1;
}
void push_back(const ValueT &value)
{
this->emplace_back(value);
}
void push_back(ValueT && value)
{
this->emplace_back( ::std::move(value) );
}
template<typename... ArgsT>
reference
emplace_back(ArgsT&&... args)
{
if( this->m_size < this->m_capacity)
{ //placement new
size_type k = this->m_size;
::new(&this->m_data[k])ValueT(::std::forward<ArgsT>(args)...);
this->m_size +=1;
return this->m_data[k];
}
//need to realloc and insert
size_type new_capacity = this->m_size+1;
new_capacity |=this->m_size/2;
auto new_data = static_cast<ValueT*>(::operator new(
new_capacity*sizeof(ValueT)));
size_type new_size = 0;
try
{
for(size_type k = 0; k < this->m_size; ++k)
{
::new(&new_data[k])ValueT(::std::move(this->m_data[k]) );
new_size +=1;
}
::new(&new_data[new_size])ValueT( ::std::forward<ArgsT>(args)...);
new_size +=1;
}
catch(const std::exception& e)
{
for( size_type k =0; k <new_size; ++k)
new_data[k].~ValueT();
::operator delete(new_data);
throw;
}
//free the past
for(size_type k = 0; k < this->m_size; ++k)
this->m_data[k].~ValueT();
if(this->m_data)
::operator delete(this->m_data);
this->m_data = new_data;
this->m_size = new_size;
this->m_capacity = new_capacity;
return this->m_data[this->m_size-1];
}
};
}//namespace my
int main()
{
using my::vector;
vector<int> vec;
int a = 2;
vec.push_back(1);
vec.emplace_back(12);
vec.emplace_back(::std::move(a));
for(const auto & v :vec)
::std::cout<<v<<::std::endl;
::std::string str;
str.emplace();
vector<::std::string> ve;
ve.emplace_back("hello");
ve.emplace_back("hello", 2);
for(const auto & v :ve)
::std::cout<<v<<::std::endl;
return 0;
}
iterator_traits实现::std::distance
#include <iterator>
#include <typeinfo>
#include <iostream>
#include <list>
#include <forward_list>
#include <vector>
using list =::std::list<int>;
using forward_list = ::std::forward_list<int>;
using vector = ::std::vector<int>;
//SFINAE substitution failure is not a error
template<class InputIterator>
typename ::std::iterator_traits<InputIterator>::difference_type distance_help(::std::forward_iterator_tag, InputIterator from, InputIterator to)
{
typename ::std::iterator_traits<InputIterator>::difference_type ret = {};
while( from != to)
from++, ret+=1;
return ret;
}
template<class InputIterator>
typename ::std::iterator_traits<InputIterator>::difference_type distance_help(::std::random_access_iterator_tag, InputIterator from, InputIterator to)
{
return to -from;
}
template<class InputIterator>
typename ::std::iterator_traits<InputIterator>::difference_type my_distance(InputIterator from, InputIterator to)
{
// typename ::std::iterator<InputIterator>::iteraor_category
return distance_help( typename ::std::iterator_traits<InputIterator>::iterator_category(), from, to);
}
int main()
{
vector vec ={1,2,3,4};
list li ={1,2,3,4};
forward_list f_list = {1,2,3,4};
::std::cout<<"the distance of vec is: "<<my_distance(vec.begin(), vec.end())<<::std::endl;
::std::cout<<"the distance of li is: "<<my_distance(li.begin(), li.end())<<::std::endl;
::std::cout<<"the distance of f_list is: "<<my_distance(f_list.before_begin(), f_list.end())<<::std::endl;
}
enum class
#include <iostream>
enum ECard : uint64_t;
enum Uid : uint64_t;
class Player : public ::std::string
{
ECard m_card;
Uid m_uid;
public:
Player()
{
m_card ={};
m_uid ={};
}
ECard get_card(Uid& uid, ECard & ecard) const noexcept
{
if( this->m_card == ecard && this->m_uid == uid)
return m_card;
return {};
}
};
int main()
{
ECard card = ECard(21212121);
Uid uid =Uid(123);
Player play;
std::cout<<play.get_card(uid, card)<<std::endl;
}
以上是关于c++标准库源码学习笔记的主要内容,如果未能解决你的问题,请参考以下文章
STL标准库 & 范型编程学习笔记:C++学习网站STL六大部件介绍
STL标准库 & 范型编程学习笔记:C++学习网站STL六大部件介绍