探究stl

探究stl,第1张

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录
  • 系列文章目录
  • 前言
  • 一、重写STL建议
  • 二、c++新特性keyword(言简意赅)
    • 1.explicit和implicit
    • 2.noexcept
  • 三、type_trait
  • 四、construction
  • 五、util
    • 1 move和forward
    • 2 pair


前言

帮助c++初学者更加友好的了解c++STL源码剖析


提示:以下是本篇文章正文内容,下面案例可供参考

一、重写STL建议

STL可分为容器(containers)、迭代器(iterators)、空间配置器(allocator)、配接器(adapters)、算法(algorithms)、仿函数(functors)六个部分。type_trait->construction->util

二、c++新特性keyword(言简意赅) 1.explicit和implicit

首先在了解keyword之前你得先了解隐式转换(implicit conversion)和显示转换(explicit conversion)

 int a=1;//编译器帮你做的转换-explicit
 float b =(float)a//强制转换-implicit

然后让我们来了解 keyword
explicit:在C++语言中,类中的构造函数如果只含有一个参数,默认情况下存在一种隐式转换,即定义了转换为此类类型的隐式转换机制。然而,这种机制并非总是合理的,甚至容易产生错误,因此,新标准增加了explicit关键字,用来限制隐式转换。

class Test {
public:
Test(); // 空构造函数
Test(double a); // 含一个参数的构造函数
Test(int a, int b); // 含两个参数的构造函数
Test(int a, double b = 1.2); // 带有默认初始值的构造函数
~Test();
};

// 调用
Test d1(12.3); // 直接调用含一个参数的构造函数
Test d2 = 1.2; // 也是调用含有一个参数的构造函数,但是包含一次隐式转换
Test d3(12, 13);
Test d3 = 12; // 隐式转换,调用带有默认初始值的构造函数Test(int a, double b = 1.2)

explicit可以阻止构造函数的隐式转换,但是只能对含有一个参数,或者有n个参数,但是其中 n-1 个参数是带有默认值的构造函数有效,其余的构造函数,explicit无法进行约束

class Test {
public:
    Test() {}  // 空构造函数
    explicit Test(double a); // 该构造函数无法进行隐式类类型转换
    explicit Test(int a, int b);  // 含有两个参数,explicit对其无效,然而该构造函数本身也是不能隐式转换的
    explicit Test(int a, double b = 1.2);  // 该构造函数无法进行隐式类类型转换
    ~Test() {}
};

// 调用
Test d1(12.3);  // 正确
Test d2 = 1.2;  // 错误,不能进行隐式类类型转换
Test d3(12, 13);  // 正确
Test d3 = 12;  // 错误,不能进行隐式类类型转换

https://blog.csdn.net/readyone/article/details/112371671
implicit:
与其相对应的implicit则代表着隐式的类构造函数,因为在默认的情况下,类构造函数都是隐式的,所以后者没有前者常用,也较少被提及。

2.noexcept

表示函数不会抛出异常的动态异常声明throw()也被新的noexcept异常声明所取代。
https://blog.csdn.net/LaoJiu_/article/details/50781352

三、type_trait

代码解析:

namespace mystl
{

// helper struct

template <class T, T v>
struct m_integral_constant
{
  static constexpr T value = v;
};

template <bool b>
using m_bool_constant = m_integral_constant<bool, b>;//c++ using 使用:取别名
//重命名
typedef m_bool_constant<true>  m_true_type;//省略 一个模板参数 b 
typedef m_bool_constant<false> m_false_type;

/*****************************************************************************************/
// type traits

// is_pair

// --- forward declaration begin
template <class T1, class T2>
struct pair;
// --- forward declaration end

template <class T>
struct is_pair : mystl::m_false_type {};//继承

template <class T1, class T2>
struct is_pair<mystl::pair<T1, T2>> : mystl::m_true_type {};

} // namespace mystl
四、construction

代码如下:


namespace mystl
{

// construct 构造对象

template <class Ty>
void construct(Ty* ptr)
{
  ::new ((void*)ptr) Ty();//全局参数
}

template <class Ty1, class Ty2>
void construct(Ty1* ptr, const Ty2& value)
{
  ::new ((void*)ptr) Ty1(value);//使用new 来 构造  一个copy construct :value
}

template <class Ty, class... Args>//init 列表 :(1,3,5,6)作为参数
void construct(Ty* ptr, Args&&... args)
{
  ::new ((void*)ptr) Ty(mystl::forward<Args>(args)...);//完美保持右值属性 参考:
}

// destroy 将对象析构

template <class Ty>
void destroy_one(Ty*, std::true_type) {}

template <class Ty>
void destroy_one(Ty* pointer, std::false_type)
{
  if (pointer != nullptr)
  {
    pointer->~Ty();
  }
}

template <class ForwardIter>
void destroy_cat(ForwardIter , ForwardIter , std::true_type) {}//cat 有浏览的意思  一个一个来解析(Iter:Iterator)

template <class ForwardIter>
void destroy_cat(ForwardIter first, ForwardIter last, std::false_type)
{
  for (; first != last; ++first)
    destroy(&*first);
}

template <class Ty>
void destroy(Ty* pointer)
{
// determine whether remove_all_extents_t<_Ty> is a reference type or can trivially be explicitly destroyed
  destroy_one(pointer, std::is_trivially_destructible<Ty>{});//
}

template <class ForwardIter>
void destroy(ForwardIter first, ForwardIter last)
{
  destroy_cat(first, last, std::is_trivially_destructible<
              typename iterator_traits<ForwardIter>::value_type>{});
}
五、util 1 move和forward
function:
//function;std::move是为性能而生。
//std::move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝。
//用法 :
//原lvalue值被moved from之后值被转移, 所以为空字符串.
typename std::remove_reference<T>::type&& move(T&& arg) noexcept
	{
		return std::remove_reference<T>::type&& > (arg);
	}
example:
int main()
{
	std::string a = "shdsda";
	std::string b = std::move(a);
	std::cout << a << std::endl;
	std::cout << b << std::endl;
}//printf:a ‘空’
	template <class T>
	T&& forward(typename std::remove_reference<T>::type& arg) noexcept
	{
		return static_cast<T&&>(arg);//
	}
	//保证右值属性
	//首先, forward常用于template函数中, 使用的时候必须要多带一个template参数T: forward, 代码略复杂;

//还有, 明确只需要move的情况而用forward, 代码意图不清晰, 其他人看着理解起来比较费劲.

//更技术上来说, 他们都可以被static_cast替代. 为什么不用static_cast呢? 也就是为了读着方便易懂.
2 pair

顾名思义:
条件判断

struct pair
{
  typedef Ty1    first_type;
  typedef Ty2    second_type;

  first_type first;    // 保存第一个数据
  second_type second;  // 保存第二个数据
  

template <class Other1 = Ty1, class Other2 = Ty2,
    typename = typename std::enable_if<//如果ture 就void
    std::is_default_constructible<Other1>::value &&
    std::is_default_constructible<Other2>::value, void>::type>
    constexpr pair(): first(), second(){}//typename = typename 
    //由于第二个模板参数的类型是依赖模板lfEnableIf的嵌套类型,
    //因此您需要使用关键字typename来告诉编译器成员Type实际上是指类型而不是其他东西(即消除歧义)。//
    //同样,模板的第二个参数是无名的,但如果您愿意,可以给它命名。它不会改变任何东西
  };

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/867125.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-12
下一篇2022-05-12

发表评论

登录后才能评论

评论列表(0条)

    保存