C++笔记(体系结构与内核分析)

news2024/11/28 16:50:17

1.OOP面向对象编程 vs. GP泛型编程

  • OOP将data和method放在一起,目的是通过封装、继承、多态提高软件的可维护性和可扩展性
  • GP将data和method分开,可以将任何容器与任何算法结合使用,只要容器满足塞饭所需的迭代器类型

2.算法与仿函数的区别

bool strLonger(const string &s1, const string &s2)
{
	return s1.size() < s2.size();
}

// 算法
cout << "max of zoo and hello:" << max(string("zoo"), string("hello")) << endl;
// 仿函数
cout << "max of zoo and hello:" << max(string("zoo"), string("hello"), strLonger) << endl;

3.泛化、特化、偏特化

  • 泛化:支持广泛的数据类型和情况,而不是针对特定类型
  • 特化:为特定类型或一组类型提供特定的实现
#include <iostream>

// General template
template <typename T>
void print(T arg) {
    std::cout << "General print: " << arg << std::endl;
}

// Specialization for const char*
template <>
void print<const char*>(const char* arg) {
    std::cout << "Specialized print for const char*: " << arg << std::endl;
}

int main() {
    print(123);             // Uses general template
    print("Hello, world");  // Uses specialized template
}
  • 偏特化:针对特定类型组合提供优化的行为或特殊实现。完全特化需要指定模板的所有参数,偏特化只需指定部分参数,或对参数施加某些约束。
    • 第一种偏特化处理第二个模板参数为 int 的情况。
    • 第二种偏特化处理两个模板参数相同的情况。
#include <iostream>

// 基本模板
template <typename T, typename U>
class MyClass {
public:
    void print() {
        std::cout << "Base template\\n";
    }
};

// 偏特化:特化第二个类型为 int 的情况
template <typename T>
class MyClass<T, int> {
public:
    void print() {
        std::cout << "Partially specialized template for T and int\\n";
    }
};

// 偏特化:特化两个类型都为相同类型的情况
template <typename T>
class MyClass<T, T> {
public:
    void print() {
        std::cout << "Partially specialized template for T, T\\n";
    }
};

int main() {
    MyClass<double, double> myClass1;  // 会匹配 MyClass<T, T>
    MyClass<double, int> myClass2;     // 会匹配 MyClass<T, int>
    MyClass<double, char> myClass3;    // 会匹配基本模板 MyClass<T, U>

    myClass1.print();  // 输出: Partially specialized template for T, T
    myClass2.print();  // 输出: Partially specialized template for T and int
    myClass3.print();  // 输出: Base template
}

4.分配器allocates

分配器(allocators)是用来管理内存分配和回收的对象。

  • 在 VC6 中,operator new() 通常通过调用 malloc() 实现, malloc() 函数不仅会开辟用户请求的内存外,还会引入额外的内存开销
void* operator new(size_t size) {
    void* p = malloc(size);
    if (p == 0) // 如果malloc失败,则抛出std::bad_alloc异常
        throw std::bad_alloc();
    return p;
}
  • 例如:当我们需要分配512个整型数据时
int *p = allocator<int>().allocate(512,(int *)0);
allocator<int>().deallocate(p,512);
  • 在 VC6 / BC++ / G++中,allocator 类都是使用 operator new 来分配内存,并使用 operator delete 来释放内存。其中,operator new() 通常通过调用 malloc() 实现开辟内存,operator delete() 通常通过调用 free() 实现回收内存:
// VC6 STL中容器对allocator的使用
template<class _Ty, class _A=allocator<_Ty>>  // 调用allocator类
class vector
{ ...
};
template <typename T>
class allocator {
public:
    typedef size_t    size_type; // size_t是一个无符合整型数据类型
    typedef ptrdiff_t difference_type;  // 表示同一个数组中任意两个元素之间的差异
    typedef T*        pointer;
    typedef T         value_type;

    pointer allocate(size_type n, const void* hint = 0) {
        return (pointer) (::operator new(n * sizeof(value_type)));
    }

    void deallocate(pointer p, size_type n) {
        ::operator delete(p);
    }
}
  • 在GCC2.9中
// VC6 STL中容器对allocator的使用
template<class T, class Alloc = alloc>  // 调用allocator类
class vector
{ ...
};

 

①内存池:由一系列内存块组成,每块预分配一定数量的内存。

②自由列表:每个固定大小的内存块都有自己的自由列表。

③大小分类:根据内存请求的大小被分类到不同的自由列表。

  • GCC4.9所附的标准库,其中**__pool_alloc就是GCC2.9中的alloc**

    // 使用方法
    vector<string, __gnn_cxx::__pool_alloc<string>> vec;
    

5.容器的分类

 

6.容器list

G2.9版本:

template <class T, class Alloc = alloc>
class list{
protected:
		typeof __list_node<T> list_node;  // 1号代码块
public:
		typeof list_node* link_type;
		typeof __list_iterator<T,T&,T*> iterator;  // 2号代码块
protected:
		link_type node;
}
// 1号代码块
template <class T>
struct __list_node {
		void* prev;
		void* next;
		T data;
};
// 2号代码块
template <class T,class Ref,class Ptr>
struct __list_iterator{
		typedef bidirectional_iterator_tag iterator_category;  // (1)
		typedef T  value_type;  // (2)
		typedef Ptr pointer;  // (3)
		typedef Ref reference;  // (4)
		typedef ptrdiff_t difference_type;  // (5)
		typedef __list_node<T> list_node;
		typedef list_node* list_type;
		typedef __list_iterator<T,Ref,Ptr> self;
		
		link_type node;
		reference operator*() const{ return (*node).data; }  // 返回引用
		pointer operator->() const{ return &(operator *());}  // 返回指针。获得该对象的内存地址,即一个指向该对象的指针
		self& operator++()   // i++
		{ node = (link_type) ((*node).next); return *this; // 返回自身的引用}
		// (*node).next是一个 __list_node<T>* 类型的值,加上(list_type)是显式类型转换
	  // (*node).next 等价于 node->next 等价于 (&(*node))->next;
	  // node只是一个迭代器的指针,不是迭代器本身
	  // self&表示返回迭代器的引用
		self operator++(int)   // ++i
		{ self tmp = *this; ++*this; return tmp;}
};
  • 前缀递增 (operator++()) 将迭代器向前移动到下一个元素
  • 后缀递增 (operator++(int)) 返回迭代器的一个临时副本(在递增前的状态),然后再递增迭代器。
  • 内置 -> 操作符 用于直接从指针访问对象成员。
  • 重载的 operator->() 提供了一种方式,通过迭代器对象模拟原生指针的行为,允许通过迭代器间接访问对象成员。
  • (*node).next等价于node->next 等价于 (&(*node))->next

G4.9版本:

template<typename _Tp, typename _Alloc=std::allocator<_Tp>>
class list:protected_List_base<_Tp,_Alloc>
{
public:typedef _List_iterator<_Tp> iterator;
}
  • template<typename _Tp, typename _Alloc = std::allocator<_Tp>>
    • 这是一个类模板,接受两个模板参数。
    • _Tp 表示列表中要存储的数据类型。
    • _Alloc 是分配器类型,用于控制链表中元素的内存分配。这个参数有一个默认值,即 std::allocator<_Tp>,这是 C++ 标准库提供的一种通用内存分配器。
  • : protected _List_base<_Tp, _Alloc>
    • list 类从 _List_base 类继承而来,使用保护(protected)继承。这意味着 _List_base 中的公共和保护成员在 list 类中将变为保护成员。
    • _List_base 是一个实现链表基础功能的类
template<typename _Tp>
struct _List_iterator
{
		typedef _Tp* pointer;
		typedef _Tp& reference;
		...
};
// 自身类型的指针使得可以从任何一个节点开始
// 沿着链表向前或向后移动,这对于双向遍历和双向操作非常重要。
struct _List_node_base
{
		_List_node_base* _M_next;
		_List_node_base* _M_prev;
};
template<typename _Tp>
struct _List_node:public _List_node_base
{
		_Tp _M_data;
};

7.Iterator必须提供5中associated types

算法提问:

template<typename T>
incline void
algorithm(T first, T last)  // 迭代器
{
		...
		T::iterator_category
		T::value_type
		T::pointer
		T::reference
		T::difference_type
		...
};

迭代器回答:

template <class T,class Ref,class Ptr>
struct __list_iterator{
		typedef bidirectional_iterator_tag iterator_category;  // (1)
		typedef T  value_type;  // (2)
		typedef Ptr pointer;  // (3)
		typedef Ref reference;  // (4)
		typedef ptrdiff_t difference_type;  // (5)
	...
};

8. iterator_traits 类型萃取

但当我们向算法中传入的是指针,而不是迭代器时,就需要用到traits。也就是说,iterator_traits 为所有类型的迭代器(包括原生指针)提供统一的方式来访问迭代器的属性,是在 <iterator> 头文件中定义的。

作用:

std::iterator_traits 模板用于提取迭代器相关的类型信息。

举例:

#include<iostream>
#include<iterator>
#include<vector>

template<typename Iterator>
void print_vector(Iterator first, Iterator last)
{
		// using关键字用来定义类型的别名
		// typename关键字告诉编译器这是一个依赖于模版参数Iterator的类型,而不是变量
		using ValueType = typename iterator_traits<Iterator>::value_type;
}

int main()
{
		vector<int> v = {1,2,3,4,5};
		print_vector(v.begin(), v.end());
}
// 当Iterator是一个类时
template<class Iterator>
struct iterator_traits
{
		typedef typename Iterator::value_type value_type;
};

// 两种偏特化情况
// 当Iterator是一个普通指针时
// 如int*,那么T为int,得到value_type就被定义为“int”
template<class T>
struct iterator_traits<T*>
{
		typedef T value_type;
};

// 当Iterator是一个常量指针(指针的指向可以修改,指针指向的值不能修改)
template<class T>
struct iterator_traits<const T*>
{
		typedef T value_type;
};
  • Iterator若是int*,ValueType 就是 int
  • Iterator若是const int*,ValueType 还是 int
  • 因为如果 ValueType 是 const int,后续再使用ValueType创建其他容器时,就会受到限制。因为标准库中的容器(如 std::vector)不能存储常量类型的元素,它们需要能被赋值和移动。

完整的iterator_traits:

template<class Iterator>
struct iterator_traits
{
		typedef typename Iterator::iterator_category iterator_category;
		typedef typename Iterator::value_type value_type;
		typedef typename Iterator::pointer iterator_category;
		typedef typename Iterator::reference reference;
		typedef typename Iterator::difference_type difference_type;
};

template<class T>
struct iterator_traits<T*>
{
		typedef random_access_iterator_tag iterator_category;
		typedef T value_type;
		typedef ptrdiff_t difference_type;
		typedef T* pointer;
		typedef T& reference;
};

template<class T>
struct iterator_traits<const T*>
{
		typedef random_access_iterator_tag iterator_category;
		typedef T value_type;
		typedef ptrdiff_t difference_type;
		typedef const T* pointer;
		typedef const T& reference;
};

9.容器vector

定义:

template <class T, class Alloc = std::allocator<T>>
class vector
{
public:
		typedef T value_type;
		typedef T* pointer;
		typedef &T reference;
		typedef size_t size_type;
protected:
		iterator **start**;
		iterator **finish**;
		iterator **end_of_range**;
		Allocator alloc;
public:
		iterator begin() { return **start**;}
		iterator end() { return **finish**;}
		size_type size const { return size_type(end() - start());}
		size_type capacity() const
		{ return size_type(**end_of_storage** - begin());}
		bool empty() const { return begin() == end();}
		reference operator[](size_type n}
		{return *(begin()+n);
		referebce front() {return *begin();}
		reference back() {return *(end()-1);}
};

push_back操作源码:

template <class T, class Alloc=std::allocator<T>>
void push_back(const T& value)
{
	if(finish == end_of_storage)  // 原始空间不足
	{
		 size_type old_size = size();
		 // old_size == 0:当前vector中没有任何元素,新分配的存储空间至少有一个元素的容量
		 // old_size != 0:分配新的容量将是当前大小的两倍, 称为指数增长
		 size_type new_capacity = old_size == 0 ? 1 : 2 * old_size;
		 iterator new_start = alloc.allocator(new_capacity);
		 iterator new_finsih = new_start;
		 try{
					// 将原数据移动到新空间
				 for(iterator old_iter = start; old_iter != finish; )
				 {
						 alloc.construct(new_finish++, *old_iter);
						 alloc.destroy(old_iter++);
				 }
				 // 添加新元素
				 alloc.construct(new_finish++, value);
		 }catch(...){
				 // 如果构造失败,释放已分配的内存
				 for(iterator it=new_start; it!=new_finish; ++it)
				 {
						 alloc.destory(it);
				 }
				 alloc.deallocate(new_start, new_capacity);
				 throw;  // 重新抛出当前异常
			}
			// 释放旧空间
      if (start) {
          alloc.deallocate(start, end_of_storage - start);
      }
      // 更新指针
      start = new_start;
      finish = new_finish;
      end_of_storage = start + new_capacity;
  } 
  else 
  {
      alloc.construct(finish++, value); // 有足够空间,直接构造新元素
  }
}

vector的迭代器iterator:

template <class T, class Alloc = alloc>
class vector
{
public:
		typedef T value_type;
		typedef T* iterator;
};

// 调用方法
vectot<int> v;
vector<int>::iterator it = v.begin();

10.容器deque

 


// BufSize是指缓冲区buffer的长度
template<class T,class Alloc = alloc, size_t BufSize=0>
class deque
{
public:
		typedef T value_type;
		typedef size_t size_type;
		typedef __deque_iterator<T,T&,T*,BufSiz> iterator;
protected:
		typedef T** map_pointer;  // 指向指针数组的指针
protected:
		iterator start;
		iterator finish;
		map_point map;  // 指向指针数组的指针,每一个都指向一个缓冲区
		size_type map_size;
public:
		iterator begin() {return start;}
		iterator end() {return finish;}
		size_type size() {return finish - start;}
		...
};

deque的迭代器iterator:

template<class T, class Ref, class Ptr, size_t BufSize>
struct __deque_iterator
{
		typedef random_access_iterator_tag iterator_category;
		typedef T value_type;
		typedef Ref reference; // T&
		typedef Ptr pointer; // T*
		typedef size_t size_type;
		typedef ptrdiff_t difference_type;
		typedef T** map_pointer;
		typedef __deque_iterator<T,Ref,Ptr,BufSiz> self;
		
		T* **cur**;
		T* **first**;
		T* **last**;
		map_point **node**;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1668382.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android性能:高版本Android关闭硬件加速GPU渲染滑动卡顿掉帧

Android性能&#xff1a;高版本Android关闭硬件加速GPU渲染滑动卡顿掉帧 如果在Androidmanifest.xml配置&#xff1a; <application android:hardwareAccelerated"false" > 或者某个特点View使用代码&#xff1a; myView.setLayerType(View.LAYER_TYPE_SOFT…

【Python-爬虫】

Python-爬虫 ■ 爬虫分类■ 1. 通用网络爬虫&#xff1a;&#xff08;搜索引擎使用&#xff0c;遵守robots协议&#xff09;■ robots协议&#xff08;君子协议&#xff09; ■ 2. 聚集网络爬虫&#xff1a;自己写的爬虫程序 ■ urllib.request&#xff08;要导入的模块&#x…

字典是如何实现的?Rehash 了解吗?

字典是 Redis 服务器中出现最为频繁的复合型数据结构。除了 hash 结构的数据会用到字典外&#xff0c;整个 Redis 数据库的所有 key 和 value 也组成了一个 全局字典&#xff0c;还有带过期时间的 key 也是一个字典。(存储在 RedisDb 数据结构中) 字典结构是什么样的呢&#xf…

PDF Squeezer for Mac,让PDF压缩更高效

还在为PDF文件过大而烦恼吗&#xff1f;试试PDF Squeezer for Mac吧&#xff01;它拥有强大的压缩功能&#xff0c;可以快速将PDF文件压缩至更小的体积&#xff0c;让你的文件传输更快捷。同时&#xff0c;它还支持多种压缩方式&#xff0c;满足你的不同需求。赶快下载体验吧&a…

【机器学习300问】88、什么是Batch Norm算法?

一、什么是Batch Norm&#xff1f; &#xff08;1&#xff09;Batch Norm的本质 神经网络中的Batch Normalization&#xff08;批量归一化&#xff0c;简称BatchNorm或BN&#xff09;是一种改进神经网络训练过程的规范化方法&#xff0c;BatchNorm的主要目的是加速神经网络的训…

每日两题 / 23. 合并 K 个升序链表 94. 二叉树的中序遍历(LeetCode热题100)

23. 合并 K 个升序链表 - 力扣&#xff08;LeetCode&#xff09; 若lists有k个元素&#xff0c;调用k - 1次&#xff08;两个有序链表的合并&#xff09;即可 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNod…

【Delphi】OpenCV 实战(一):OpenCV简介及开发环境配置

目录 一、OpenCV 功能模块 二、Delphi 中使用OpenCV 三、OpenCV 4.7 Delphi开发环境配置 1. 环境配置 2. OpenCV 中Demo程序的编译配置 3. 运行 Demo (OpenCV for Delphi) OpenCV 是世界上最大的计算机视觉库。 它是开源的,包含 2500 多种算法,由非营利…

八、VUE内置指令

一、初识VUE 二、再识VUE-MVVM 三、VUE数据代理 四、VUE事件处理 五、VUE计算属性 六、Vue监视属性 七、VUE过滤器 七、VUE内置指令 九、VUE组件 v-text 向其所在的节点中渲染文本内容。 (纯文本渲染)与插值语法的区别&#xff1a;v-text会替换掉节点中的内容&#xff0c;{{x…

技术爱好者必看:如何用AI问答API彻底改变用户体验!

AI 问答 API 对接说明 我们知道&#xff0c;市面上一些问答 API 的对接还是相对没那么容易的&#xff0c;比如说 OpenAI 的 Chat Completions API&#xff0c;它有一个 messages 字段&#xff0c;如果要完成连续对话&#xff0c;需要我们把所有的上下文历史全部传递&#xff0…

猫头虎分享已解决Bug || **Vue.js脚手架安装失败** Error: unable to fetch template`

猫头虎分享已解决Bug &#x1f42f; || Vue.js脚手架安装失败 &#x1f6ab;Error: unable to fetch template 博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题…

Maven多环境与SpringBoot多环境配置

1. Maven多环境配置与应用 1.1 多环境开发 我们平常都是在自己的开发环境进行开发&#xff0c; 当开发完成后&#xff0c;需要把开发的功能部署到测试环境供测试人员进行测试使用&#xff0c; 等测试人员测试通过后&#xff0c;我们会将项目部署到生成环境上线使用。 这个时…

Django——会话.CookieSession

Django——会话.Cookie&Session 一、Cookie 会话指的是浏览器与web服务器之间的通信。HTTP协议是无状态协议。web服务器无法知道用户上一次会话数据&#xff0c;用来维护用户在访问网站过程中的状态 &#xff0c; 会话控制使用 Cookie 和 Session 一起实现。 通常把 Ses…

maven远程仓库访问顺序

首先需要了解一下各个配置文件&#xff0c;主要分为三类&#xff1a; 全局配置文件(${maven.home}/conf/settings.xml)&#xff0c;maven安装路径下的/conf/settings.xml用户配置文件(%USER_HOME%/.m2/settings.xml)&#xff0c;windows用户文件夹下项目配置文件&#xff1a;p…

【JVM基础篇】类加载器分类介绍

文章目录 类加载器什么是类加载器类加载器的作用是什么应用场景类加载器的分类启动类加载器用户扩展基础jar包 扩展类加载器和应用程序类加载器扩展类加载器通过扩展类加载器去加载用户jar包&#xff1a; 应用程序加载器 Arthas中类加载器相关功能 文章说明 类加载器 什么是类…

【Gitlab远程访问本地仓库】Gitlab如何安装配置并结合内网穿透实现远程访问本地仓库进行管理

文章目录 前言1. 下载Gitlab2. 安装Gitlab3. 启动Gitlab4. 安装cpolar5. 创建隧道配置访问地址6. 固定GitLab访问地址6.1 保留二级子域名6.2 配置二级子域名 7. 测试访问二级子域名 前言 GitLab 是一个用于仓库管理系统的开源项目&#xff0c;使用Git作为代码管理工具&#xf…

数据结构与算法学习笔记之线性表二---顺序表的静态存储表示和实现(C++)

目录 前言 1.什么是顺序表 2.顺序表的静态存储表示 1.初始化 2.长度 3.数据元素 4.长度 5.获取元素下标 6.前驱节点 7.后继节点 8.插入 9.删除 10.遍历 11.测试代码 前言 这篇文章讲的是顺序表的两种实现方式。 1.什么是顺序表 线性表的顺序表示指的是用一组地址…

用hMailServer+roundcubemail+宝塔安装配置一个自己的邮箱服务

用hMailServerroundcubemail安装配置一个自己的邮箱服务 1、准备工具与资料&#xff1a; 云服务器一台 基础配置就行 2核4G。域名一个 以下用lizipro.cn示例。hMailServer安装包roundcubemail安装包异常处理插件补丁&#xff1a; libmysql.zip 2、hMailServer服务安装&#…

通过内网穿透免费部署我们的springboot+vue项目 实现跟服务器一样的效果

前文讲到通过内网穿透能够实现远程访问个人电脑的静态资源。本文将讲解通过内网穿透实现远程访问本地的项目&#xff0c;实现跟部署到服务器一样的效果&#xff1a;前文链接&#xff1a;通过内网穿透实现远程访问个人电脑资源详细过程&#xff08;免费&#xff09;&#xff08;…

MFC重要的初始化函数InitInstance

MFC应用程序最早处理的类的初始化函数通常是CWinApp类的构造函数。CWinApp类是MFC应用程序的主类&#xff0c;负责整个应用程序的初始化和管理。 在MFC应用程序中&#xff0c;通常会创建一个派生自CWinApp类的应用程序类&#xff0c;例如CMyApp。在应用程序启动时&#xff0c;…

MySQL——系统变量

使用 #最大连接用户数 select MAX_CONNECTIONS; #临时存放构成每次事务的SQL的缓冲区长度 select BINLOG_CACHE_SIZE; #SQL Server的版本信息 select VERSION; 查询结果