提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 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则代表着隐式的类构造函数,因为在默认的情况下,类构造函数都是隐式的,所以后者没有前者常用,也较少被提及。
表示函数不会抛出异常的动态异常声明throw()也被新的noexcept异常声明所取代。
https://blog.csdn.net/LaoJiu_/article/details/50781352
代码解析:
namespace mystl
{
// helper struct
template
struct m_integral_constant
{
static constexpr T value = v;
};
template
using m_bool_constant = m_integral_constant;//c++ using 使用:取别名
//重命名
typedef m_bool_constant m_true_type;//省略 一个模板参数 b
typedef m_bool_constant m_false_type;
// type traits
// is_pair
// --- forward declaration begin
template
struct pair;
// --- forward declaration end
template
struct is_pair : mystl::m_false_type {};//继承
template
struct is_pair> : mystl::m_true_type {};
} // namespace mystl
四、construction
代码如下:
namespace mystl
{
// construct 构造对象
template
void construct(Ty* ptr)
{
::new ((void*)ptr) Ty();//全局参数
}
template
void construct(Ty1* ptr, const Ty2& value)
{
::new ((void*)ptr) Ty1(value);//使用new 来 构造 一个copy construct :value
}
template //init 列表 :(1,3,5,6)作为参数
void construct(Ty* ptr, Args&&... args)
{
::new ((void*)ptr) Ty(mystl::forward(args)...);//完美保持右值属性 参考:
}
// destroy 将对象析构
template
void destroy_one(Ty*, std::true_type) {}
template
void destroy_one(Ty* pointer, std::false_type)
{
if (pointer != nullptr)
{
pointer->~Ty();
}
}
template
void destroy_cat(ForwardIter , ForwardIter , std::true_type) {}//cat 有浏览的意思 一个一个来解析(Iter:Iterator)
template
void destroy_cat(ForwardIter first, ForwardIter last, std::false_type)
{
for (; first != last; ++first)
destroy(&*first);
}
template
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{});//
}
template
void destroy(ForwardIter first, ForwardIter last)
{
destroy_cat(first, last, std::is_trivially_destructible<
typename iterator_traits::value_type>{});
}
五、util
1 move和forward
function: //function;std::move是为性能而生。 //std::move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝。 //用法 : //原lvalue值被moved from之后值被转移, 所以为空字符串. typename std::remove_reference2 pair::type&& move(T&& arg) noexcept { return std::remove_reference ::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 T&& forward(typename std::remove_reference ::type& arg) noexcept { return static_cast (arg);// } //保证右值属性 //首先, forward常用于template函数中, 使用的时候必须要多带一个template参数T: forward , 代码略复杂; //还有, 明确只需要move的情况而用forward, 代码意图不清晰, 其他人看着理解起来比较费劲. //更技术上来说, 他们都可以被static_cast替代. 为什么不用static_cast呢? 也就是为了读着方便易懂.
顾名思义:
条件判断
struct pair
{
typedef Ty1 first_type;
typedef Ty2 second_type;
first_type first; // 保存第一个数据
second_type second; // 保存第二个数据
template ::value &&
std::is_default_constructible::value, void>::type>
constexpr pair(): first(), second(){}//typename = typename
//由于第二个模板参数的类型是依赖模板lfEnableIf的嵌套类型,
//因此您需要使用关键字typename来告诉编译器成员Type实际上是指类型而不是其他东西(即消除歧义)。//
//同样,模板的第二个参数是无名的,但如果您愿意,可以给它命名。它不会改变任何东西
};



