当前位置: 首页 > news >正文

【C++篇】领略模板编程的进阶之美:参数巧思与编译的智慧

文章目录

  • C++模板进阶编程
    • 前言
    • 第一章: 非类型模板参数
      • 1.1 什么是非类型模板参数?
        • 1.1.1 非类型模板参数的定义
      • 1.2 非类型模板参数的注意事项
      • 1.3 非类型模板参数的使用场景
        • 示例:静态数组的实现
    • 第二章: 模板的特化
      • 2.1 什么是模板特化?
        • 2.1.1 模板特化的分类
      • 2.2 函数模板特化
        • 示例:函数模板的特化
    • 第三章: 类模板特化
      • 3.1 类模板的全特化
        • 示例:全特化
      • 3.2 类模板的偏特化
        • 示例1:部分参数的偏特化
        • 示例2:指针类型的偏特化
      • 3.3 类模板特化的应用示例
        • 示例:对指针进行排序的类模板特化
    • 第四章: 模板的分离编译
      • 4.1 什么是模板的分离编译?
      • 4.2 分离编译中的问题
        • 示例:模板的声明和定义分离
      • 4.3 解决模板分离编译问题
    • 第五章: 模板总结
      • 优点:
      • 缺点:
    • 第六章: 模板元编程(Template Metaprogramming)
      • 6.1 什么是模板元编程?
        • 6.1.1 编译期与运行期的区别
      • 6.2 模板元编程的基础
        • 示例:使用模板元编程计算阶乘
        • 输出:
      • 6.3 使用模板元编程进行条件选择
        • 示例:编译期条件判断
      • 6.4 TMP的实际应用
    • 第七章: 模板匹配规则与SFINAE
      • 7.1 模板匹配规则
        • 7.1.1 优先调用非模板函数
        • 7.1.2 如果没有非模板函数,匹配模板实例
      • 7.2 SFINAE (Substitution Failure Is Not An Error)
        • 示例:SFINAE 规则
    • 第八章: 模板最佳实践
      • 8.1 模板的代码膨胀问题
      • 8.2 模板错误调试
    • 写在最后

C++模板进阶编程

接上篇【C++篇】引领C++模板初体验:泛型编程的力量与妙用

💬 欢迎讨论:如果你在学习过程中有任何问题或想法,欢迎在评论区留言,我们一起交流学习。你的支持是我继续创作的动力!

👍 点赞、收藏与分享:觉得这篇文章对你有帮助吗?别忘了点赞、收藏并分享给更多的小伙伴哦!你们的支持是我不断进步的动力!
🚀 分享给更多人:如果你觉得这篇文章对你有帮助,欢迎分享给更多对C++感兴趣的朋友,让我们一起进步!

前言

在C++模板编程中,基本模板的概念和用法已经能够解决大多数的编程问题,但在面对更加复杂的场景时,模板的特化、非类型模板参数以及分离编译等高级技术开始显得尤为重要。本文将详细讲解这些进阶模板知识,并结合具体示例进行剖析,帮助读者深入理解C++模板的高级用法。

第一章: 非类型模板参数

1.1 什么是非类型模板参数?

在模板编程中,除了类型参数(如 class Ttypename T)外,还可以使用非类型模板参数。非类型模板参数可以是常量,例如整数、枚举、指针等,它们在编译期间是已知的值。

1.1.1 非类型模板参数的定义

以下是一个简单的非类型模板参数的例子:

template<class T, size_t N>
class Array {
public:T& operator[](size_t index) {return _array[index];}const T& operator[](size_t index) const {return _array[index];}size_t size() const { return N; }private:T _array[N];
};

在这个例子中,N 是一个非类型模板参数,表示数组的大小,它必须在编译时已知。

1.2 非类型模板参数的注意事项

  1. 允许的类型:非类型模板参数可以是整型、枚举、指针或者引用类型,但浮点数、类对象和字符串不允许作为非类型模板参数。
  2. 编译期确认:非类型模板参数必须在编译期确认。这意味着它的值在编译时必须是一个常量表达式。

1.3 非类型模板参数的使用场景

非类型模板参数最常用于需要对某些固定值进行编译期优化的场景。例如,在实现容器类时,可以通过非类型模板参数来指定容器的大小,从而在编译时确定内存分配的规模。

示例:静态数组的实现
template<typename T, size_t N>
class StaticArray {
public:T& operator[](size_t index) {return _array[index];}const T& operator[](size_t index) const {return _array[index];}private:T _array[N];
};int main() {StaticArray<int, 10> arr;  // 创建一个大小为10的静态数组arr[0] = 1;arr[1] = 2;std::cout << arr[0] << ", " << arr[1] << std::endl;return 0;
}

在这个例子中,N 是数组的大小,编译器在编译时已经知道这个值,因此它能够直接优化内存分配和数组边界检查。


第二章: 模板的特化

2.1 什么是模板特化?

模板特化是指在模板的基础上,针对某些特定的类型提供专门的实现。当模板的默认实现无法满足某些特定类型的需求时,就可以通过特化来处理。例如,针对指针类型的特殊处理。

2.1.1 模板特化的分类

模板特化分为两种:

  1. 全特化:对模板中的所有参数进行特化。
  2. 偏特化:仅对模板中的部分参数进行特化或进一步限制。

2.2 函数模板特化

示例:函数模板的特化

以下是一个函数模板特化的示例:

template<class T>
bool Less(T left, T right) {return left < right;
}// 针对指针类型的特化
template<>
bool Less<Date*>(Date* left, Date* right) {return *left < *right;
}int main() {Date d1(2022, 7, 7);Date d2(2022, 7, 8);std::cout << Less(d1, d2) << std::endl;  // 正常比较日期Date* p1 = &d1;Date* p2 = &d2;std::cout << Less(p1, p2) << std::endl;  // 使用特化版本,比较指针指向的内容return 0;
}

在这个例子中,函数 Less 针对 Date* 指针类型进行了特化,以正确处理指针类型的比较。


第三章: 类模板特化

3.1 类模板的全特化

全特化指的是对模板中的所有参数进行特化,适用于某些特定类型,完全替代原始的模板实现。

示例:全特化
template<class T1, class T2>
class Data {
public:Data() { std::cout << "Data<T1, T2>" << std::endl; }
};template<>
class Data<int, char> {
public:Data() { std::cout << "Data<int, char>" << std::endl; }
};int main() {Data<int, int> d1;   // 使用原始模板版本Data<int, char> d2;  // 使用全特化版本
}

在这个例子中,Data<int, char> 这个类型的对象会调用全特化的版本,输出 “Data<int, char>”。

3.2 类模板的偏特化

偏特化允许对模板的一部分参数进行特化,而不需要对全部参数进行特化。它使得模板能够更灵活地处理复杂的类型组合。

示例1:部分参数的偏特化
template<class T1, class T2>
class Data {
public:Data() { std::cout << "Data<T1, T2>" << std::endl; }
};// 偏特化版本,将第二个模板参数特化为int
template<class T1>
class Data<T1, int> {
public:Data() { std::cout << "Data<T1, int>" << std::endl; }
};int main() {Data<int, char> d1;  // 调用原始模板Data<int, int> d2;   // 调用偏特化版本
}

在这里,Data<int, int> 将调用偏特化版本,而 Data<int, char> 将调用原始模板版本。

示例2:指针类型的偏特化
template<class T1, class T2>
class Data {
public:Data() { std::cout << "Data<T1, T2>" << std::endl; }
};// 偏特化版本,将两个参数特化为指针类型
template<class T1, class T2>
class Data<T1*, T2*> {
public:Data() { std::cout << "Data<T1*, T2*>" << std::endl; }
};int main() {Data<int, int> d1;      // 调用原始模板Data<int*, int*> d2;    // 调用指针类型偏特化版本
}

在这个例子中,Data<int*, int*> 将调用偏特化的指针版本,输出 “Data<T1*, T2*>”。

3.3 类模板特化的应用示例

类模板特化在处理不同类型的对象时,能够大幅提高代码的灵活性和可读性。以下是一个具体的应用场景:

示例:对指针进行排序的类模板特化
#include <vector>
#include <algorithm>template<class T>
struct Less {bool operator()(const T& x, const T& y) const {return x < y;}
};// 针对指针类型进行特化
template<>
struct Less<Date*> {bool operator()(Date* x, Date* y) const {return *x < *y;}
};int main() {Date d1(2022, 7, 7);Date d2(2022, 7, 6);Date d3(2022, 7, 8);// 排序日期对象std::vector<Date> v1 = {d1, d2, d3};std::sort(v1.begin(), v1.end(), Less<Date>());// 正确排序// 排序指针std::vector<Date*> v2 = {&d1, &d2, &d3};std::sort(v2.begin(), v2.end(), Less<Date*>());// 使用特化版本,按指针指向的日期排序return 0;
}

通过类模板特化,可以实现对指针的排序,并确保比较的是指针指向的内容而不是地址。


第四章: 模板的分离编译

4.1 什么是模板的分离编译?

分离编译指的是将程序分为多个源文件,每个源文件单独编译生成目标文件,最后将所有目标文件链接生成可执行文件。在模板编程中,分离编译有时会带来挑战,因为模板的实例化是在编译期进行的,编译器需要知道模板的定义和使用场景。

4.2 分离编译中的问题

在模板的分离编译中,模板的声明和定义分离时会产生编译或链接错误。这是因为模板的实例化是由编译器根据实际使用的类型生成的代码,如果在模板的定义和使用之间缺乏可见性,编译器无法正确地实例化模板。

示例:模板的声明和定义分离
// a.h
template<class T>
T Add(const T& left, const T& right);// a.cpp
template<class T>
T Add(const T& left, const T& right) {return left + right;
}// main.cpp
#include "a.h"int main() {Add(1, 2);        // 使用模板函数Add(1.0, 2.0);    // 使用模板函数return 0;
}

在这种情况下,由于模板的定义和使用是分离的,编译器在不同编译单元中无法找到模板的定义,从而导致链接错误。

4.3 解决模板分离编译问题

为了解决模板的分离编译问题,可以采取以下几种方法:

  1. 将模板的声明和定义放在同一个头文件中
    将模板的定义和声明都放在头文件中,使得所有使用模板的编译单元都可以访问到模板的定义。

    // a.h
    template<class T>
    T Add(const T& left, const T& right) {return left + right;
    }
    
  2. 显式实例化模板
    通过显式实例化,将模板的具体实现放在 .cpp 文件中。这样,编译器能够在实例化时找到模板的定义。

    // a.cpp
    template T Add<int>(const int& left, const int& right);
    template T Add<double>(const double& left, const double& right);
    

这两种方法都能有效避免模板分离编译带来的问题,推荐将模板的定义和声明放在同一个文件中,通常使用 .hpp.h 文件格式。


第五章: 模板总结

模板编程在C++中是一种非常强大的工具,通过泛型编程、模板特化和非类型模板参数等技术,可以编写高效、灵活的代码。模板编程的优缺点总结如下:

优点:

  1. 代码复用:模板能够极大提高代码的复用性,减少重复代码的编写。
  2. 灵活性:可以根据不同的数据类型生成特定的代码,增强了程序的适应性。
  3. STL基础:C++的标准模板库(STL)就是基于模板技术构建的,它为容器、算法和迭代器提供了高度泛型化的接口。

缺点:

  1. 代码膨胀:模板实例化时会生成不同版本的代码,可能导致二进制文件变大。
  2. 编译时间变长:由于模板的编译期实例化,可能会导致编译时间增加。
  3. 调试困难:模板编译错误信息往往非常复杂,难以阅读和调试。

第六章: 模板元编程(Template Metaprogramming)

6.1 什么是模板元编程?

模板元编程(Template Metaprogramming,简称TMP)是一种利用C++模板机制进行编译期计算和代码生成的编程技术。它主要用于在编译时生成代码,并避免运行时的计算,从而提升程序的效率。模板元编程的核心思想是通过模板递归实现逻辑运算、数学计算等操作。

6.1.1 编译期与运行期的区别

运行期计算是在程序执行过程中进行的,例如加法运算、条件判断等。

编译期计算则是在编译阶段就确定的,模板元编程可以在程序编译过程中进行某些计算,从而减少运行期的负担。C++模板系统可以进行编译期递归和选择。


6.2 模板元编程的基础

模板元编程的基础主要是利用模板的递归和特化来进行编译期计算。一个简单的例子是使用模板递归来计算阶乘

示例:使用模板元编程计算阶乘
// 基本模板
template<int N>
struct Factorial {static const int value = N * Factorial<N - 1>::value;
};// 特化版本,当N为1时终止递归
template<>
struct Factorial<1> {static const int value = 1;
};int main() {std::cout << "Factorial of 5: " << Factorial<5>::value << std::endl;return 0;
}

在这个例子中,Factorial<5> 会在编译期递归展开为 5 * 4 * 3 * 2 * 1,并计算出阶乘值。在运行时打印结果,编译器已经在编译阶段完成了计算。

输出:
Factorial of 5: 120

6.3 使用模板元编程进行条件选择

模板元编程不仅可以用来进行数学运算,还可以用于条件选择(类似于 if-else 语句),从而在编译期决定代码的生成。例如,我们可以通过模板来选择某些代码块是否在编译时生成。

示例:编译期条件判断
template<bool Condition, typename TrueType, typename FalseType>
struct IfThenElse;template<typename TrueType, typename FalseType>
struct IfThenElse<true, TrueType, FalseType> {typedef TrueType type;
};template<typename TrueType, typename FalseType>
struct IfThenElse<false, TrueType, FalseType> {typedef FalseType type;
};int main() {// 当条件为 true 时,选择 int 类型IfThenElse<true, int, double>::type a = 10;// 当条件为 false 时,选择 double 类型IfThenElse<false, int, double>::type b = 3.14;std::cout << "a: " << a << ", b: " << b << std::endl;return 0;
}

在这个例子中,IfThenElse 模板类模拟了条件选择,在编译时根据布尔值 Condition 选择 TrueTypeFalseType。如果条件为真,则选择 TrueType;否则,选择 FalseType


6.4 TMP的实际应用

模板元编程可以用于很多实际场景中,例如计算多项式、矩阵运算、位操作等。它的主要优势在于可以减少运行时的计算开销,将复杂的逻辑提前到编译时处理,提升程序的效率。


第七章: 模板匹配规则与SFINAE

7.1 模板匹配规则

C++编译器在调用模板时,会根据传入的模板参数进行匹配。模板匹配的规则比较复杂,涉及到多个优先级和模板特化。

7.1.1 优先调用非模板函数

在匹配时,编译器会优先选择非模板函数,如果有完全匹配的非模板函数存在,编译器会选择该函数,而不是实例化模板。

int Add(int a, int b) {return a + b;
}template<typename T>
T Add(T a, T b) {return a + b;
}int main() {int a = 1, b = 2;std::cout << Add(a, b) << std::endl;  // 调用非模板版本return 0;
}
7.1.2 如果没有非模板函数,匹配模板实例

如果没有完全匹配的非模板函数存在,编译器将生成模板实例化版本。

template<typename T>
T Add(T a, T b) {return a + b;
}int main() {double x = 1.1, y = 2.2;std::cout << Add(x, y) << std::endl;  // 调用模板实例化版本return 0;
}

7.2 SFINAE (Substitution Failure Is Not An Error)

SFINAE 是 C++ 模板系统中的一个重要规则,全称为 “Substitution Failure Is Not An Error”(替换失败不是错误)。SFINAE 是指在模板实例化过程中,如果某些模板参数的替换失败,编译器不会直接报错,而是选择其他可行的模板。

示例:SFINAE 规则
template<typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
CheckType(T t) {return t * 2;
}template<typename T>
typename std::enable_if<!std::is_integral<T>::value, T>::type
CheckType(T t) {return t * 0.5;
}int main() {std::cout << CheckType(10) << std::endl;   // 整数类型,输出20std::cout << CheckType(3.14) << std::endl; // 浮点数类型,输出1.57return 0;
}

在这个例子中,SFINAE 机制允许我们根据类型的不同选择不同的模板版本。在 CheckType 函数模板中,当传入的参数是整数类型时,编译器选择第一个版本,而当参数是浮点数类型时,选择第二个版本。


第八章: 模板最佳实践

8.1 模板的代码膨胀问题

模板虽然提供了极大的灵活性,但它也会带来代码膨胀问题。因为模板实例化会生成多个版本的代码,所以在大规模使用模板时,可能会导致二进制文件体积增大。为了解决这个问题,可以考虑以下几种策略:

  1. 减少模板的实例化次数:通过显式实例化来控制模板的使用,避免重复生成相同功能的模板代码。
  2. 避免过度模板化:在设计模板时,尽量避免将所有逻辑都写成模板,只有在必要时才使用模板。
  3. 使用非类型模板参数:非类型模板参数可以减少模板的泛化程度,避免代码膨胀。

8.2 模板错误调试

模板编译错误通常会产生非常复杂的错误信息,难以调试。以下是一些常用的调试模板代码的方法:

  1. 分解模板代码:将复杂的模板逻辑分解为多个小的模板函数或类,逐步进行调试。
  2. 使用静态断言:在模板代码中插入 static_assert 来检查模板参数是否合法,提前发现问题。
  3. 阅读编译错误信息:虽然模板错误信息冗长,但可以从错误的上下文中找到模板参数替换的线索,从而定位问题。

写在最后

通过对C++模板进阶技术的深入讲解,我们探索了非类型模板参数、模板特化、SFINAE以及模板元编程等高级概念,这些工具不仅使我们的代码更加灵活高效,还为我们提供了在复杂场景下优化代码的思路。在实际项目中,合理利用这些模板技术可以显著提高代码复用性、减少运行时错误,并大幅提升编译期的优化效果。希望通过本篇内容的学习,你能够更好地理解并应用这些进阶技术,在未来的C++开发中游刃有余。

以上就是关于【C++篇】解密模板编程的进阶之美:参数巧思与编译的智慧的内容啦,各位大佬有什么问题欢迎在评论区指正,或者私信我也是可以的啦,您的支持是我创作的最大动力!❤️

在这里插入图片描述

相关文章:

【C++篇】领略模板编程的进阶之美:参数巧思与编译的智慧

文章目录 C模板进阶编程前言第一章: 非类型模板参数1.1 什么是非类型模板参数&#xff1f;1.1.1 非类型模板参数的定义 1.2 非类型模板参数的注意事项1.3 非类型模板参数的使用场景示例&#xff1a;静态数组的实现 第二章: 模板的特化2.1 什么是模板特化&#xff1f;2.1.1 模板…...

golang学习笔记20-面向对象(二):方法与结构体【重要】

本节内容是面向对象的核心与基础&#xff0c;很重要。 注意&#xff1a;由于导包语句已经在19讲&#xff08;笔记19&#xff1a;面向对象的引入&#xff09;展示过了&#xff0c;所以这里就不展示了。 一、方法的定义与细节 方法是与特定类型&#xff08;通常是结构体&#x…...

广州C++信奥老师解一本通题 1919:【02NOIP普及组】选数

【题目描述】 已知nn个整数x1,x2,……xn 以及一个整数K(K&#xff1c;n)。从n个整数中任选K个整数相加,可分别 得到一系列的和。例如当n4, k3 4个整数分别为3,7,12,19 3, 7,12,19时,可得全部的组合与它们的和为: 371222   371929   7121938  3121934 现在,要求你计算出和为…...

cas5.3统一登录前后端分离改造方案(源码)

cas5.3 为什么选择cas5.3 版本 5.3 版本是最新的支持jdk8 的版本&#xff0c;并且项目架构基于maven &#xff0c;商业项目中jdk8 仍是主流&#xff0c;在考虑商业收益的情况下&#xff0c;如果客户不要求&#xff0c;不会升级jdk, 基于Maven的项目比gradle 简单&#xff0c;…...

【ComfyUI】控制光照节点——ComfyUI-IC-Light-Native

原始代码&#xff08;非comfyui&#xff09;&#xff1a;https://github.com/lllyasviel/IC-Light comfyui实现1&#xff08;600星&#xff09;&#xff1a;https://github.com/kijai/ComfyUI-IC-Light comfyui实现2&#xff08;500星&#xff09;&#xff1a;https://github.c…...

LVS+keepalived整合负载均衡配置

准备三台服务器&#xff1b;负载均衡服务器192.168.45.136&#xff0c;后端机器1&#xff0c;92.168.45.135&#xff0c;后端机器2&#xff0c;192.168.45.138 在两台后端机器上安装nginx服务&#xff0c;yum install -y nginx,并且启动nginx服务&#xff0c;systemctl start …...

Goland无法使用debug的修复

现象goland在debug的时候&#xff0c;一直卡在打的断点处&#xff0c;释放断点程序就执行结束。 查看其他博客说是当使用老版本的goland&#xff0c;golang版本为高版本时就会出现debug问题&#xff0c;需要手动更换dlv。 接下来以window为例子&#xff1a; 第一步&#xff1…...

MySQL和Doris开窗函数LAG执行时的区别

目标表的表结构 CREATE TABLE point_value_status_color_tmp ( id bigint NOT NULL, org_id varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, device_id varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, origin_ti…...

都是小憨憨!

周五晚上约了俩哥们儿吃饭&#xff0c;天南海北地聊着。其中一个哥们儿 L 讲&#xff0c;他在外面如何辛苦跑业务&#xff0c;维系客户&#xff0c;拿单子……但却被合伙人说是合伙人拉了 L 一把&#xff0c;而且可以分分钟灭了 L。所以 L 感觉到很委屈。然后我们俩就劝说趁早决…...

高级java每日一道面试题-2024年9月30日-服务器篇[Redis篇]-Redis持久化有几种方式?

如果有遗漏,评论区告诉我进行补充 面试官: Redis持久化有几种方式? 我回答: Redis 是一个高性能的键值存储系统&#xff0c;常用于缓存、消息队列和实时数据分析等场景。为了保证数据的持久性&#xff0c;Redis 提供了两种主要的持久化方式&#xff1a;RDB&#xff08;Redi…...

ICML 2024 论文分享┆一个简单且通用的交通预测提示调优框架

论文简介 本推文介绍了2024 ICML的优秀论文之一《FlashST: A Simple and Universal Prompt-Tuning Framework for Traffic Prediction》。论文的核心目标是通过整合空间和时间因素&#xff0c;精准地预测和分析交通流量的动态变化。然而&#xff0c;在交通预测领域&#xff0c…...

【C++打怪之路Lv4】-- 类和对象(中)

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;C打怪之路&#xff0c;python从入门到精通&#xff0c;数据结构&#xff0c;C语言&#xff0c;C语言题集&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文(平均质量分82)&#…...

滚雪球学MySQL[1.1讲]:MySQL简介与环境配置

全文目录&#xff1a; 前言1. MySQL简介与环境配置1.1 MySQL简介什么是MySQLMySQL的历史和版本MySQL的应用场景 1.2 安装与配置安装MySQL&#xff08;Windows、Linux、macOS&#xff09;配置文件解析&#xff08;my.cnf&#xff09;启动与停止MySQL服务 1.3 MySQL客户端工具MyS…...

Llama微调以及Ollama部署

1 Llama微调 在基础模型的基础上&#xff0c;通过一些特定的数据集&#xff0c;将具有特定功能加在原有的模型上。 1.1 效果对比 特定数据集 未使用微调的基础模型的回答 使用微调后的回答 1.2 基础模型 基础大模型我选择Mistral-7B-v0.3-Chinese-Chat-uncensored&#x…...

中关村环球时尚产业联盟 东晟时尚产业创新中心成立

2024年9月6日&#xff0c;中关村环球时尚产业联盟与东晟时尚创新科技&#xff08;北京&#xff09;有限公司于中关村科技园东城园举行了隆重的战略合作签约仪式。 中关村科技园东城园领导发表了致辞&#xff0c;并表示东城区作为首都北京的核心区域&#xff0c;拥有深厚的历史…...

基于SSM的宠物领养管理系统的设计与实现 (含源码+sql+视频导入教程+文档+PPT)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM的宠物领养管理系统2拥有两种角色 管理员&#xff1a;宠物分类管理、领养管理、宠物商品管理、用户管理、寄存管理、丢失信息管理、订单管理等 用户&#xff1a;登录注册、收藏评…...

为什么要配置环境变量?

在 Windows 操作系统中配置环境变量有多个重要的原因&#xff0c;这些原因与软件开发、系统管理和日常使用密切相关。以下是一些主要的原因&#xff1a; 1. 系统路径&#xff08;PATH&#xff09; 可执行文件的位置&#xff1a;PATH 环境变量用于指定操作系统在何处查找可执行…...

条件熵公式详细解释、举例说明计算步骤

公式 7-4 是条件熵的表达式&#xff1a; E ( Y ∣ X ) ∑ i 1 m p ( X x i ) E ( Y ∣ X x i ) E(Y|X) \sum_{i1}^m p(X x_i) E(Y | X x_i) E(Y∣X)i1∑m​p(Xxi​)E(Y∣Xxi​) 这个公式表示的是条件熵&#xff0c;它是衡量在已知某一特征 X X X 的情况下&#xff0c…...

颍川陈氏始祖陈寔逆势崛起的原由(一)不屈的努力

园子说颍川 按陈寔的出身&#xff0c;与当官是风马牛不相及的。 东汉末年的社会&#xff0c;朝中外戚、宦官当道&#xff0c;地方则由世家大族把持&#xff0c;郡县的政治经济资源都由他们掌控分配&#xff0c;平民以及中小地主很难有出头之日&#xff0c;弄不好就被兼并了。…...

golang小项目1-家庭收支记账系统

项目地址&#xff1a;golang小项目 参考资料&#xff1a;尚硅谷golang教程P229 家庭收支记账系统 1. 系统简介 1.1 项目背景 在现代社会中&#xff0c;家庭的财务管理显得尤为重要。随着生活成本的不断上升&#xff0c;家庭需要有效地记录和分析收支情况&#xff0c;以确保…...

Visual Studio Code下载安装及汉化

官网&#xff1a;https://code.visualstudio.com/ 按照指示一步步操作即可&#xff1a; 汉化&#xff1a;...

MySQL—触发器详解

基本介绍 触发器是与表有关的数据库对象&#xff0c;在 INSERT、UPDATE、DELETE 操作之前或之后触发并执行触发器中定义的 SQL 语句。 触发器的这种特性可以协助应用在数据库端确保数据的完整性、日志记录、数据校验等操作。 使用别名 NEW 和 OLD 来引用触发器中发生变化的记…...

钉钉H5微应用Springboot+Vue开发分享

文章目录 说明技术路线注意操作步骤思路图 一、创建钉钉应用二、创建java项目三、创建vue项目&#xff08;或uniapp项目&#xff09;&#xff0c;npm引入sdk的依赖四、拥有公网域名端口。开发环境可以使用&#xff08;贝锐花生壳等工具&#xff09;五、打开钉钉开发者平台&…...

项目:微服务即时通讯系统客户端(基于C++QT)]四,中间界面搭建和逻辑准备

四&#xff0c;中间界面搭建 前言:当项目越来越复杂的时候&#xff0c;或许画草图是非常好的选择 一&#xff0c;初始化中间窗口initMidWindow void mainWidget::initMidWindow() {//使用网格布局进行管理QGridLayout* layout new QGridLayout();//距离上方 20px 的距离&…...

【C语言】指针详解(一)

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1.内存与地址2.指针变量与地址2.1 取地址操作符&2.2 指针变量2.3 指针类型2.4 解引用操作符2.5 指针变量的大小 3. 指针变量类型的意义3.1 指针的解引用 4. const修饰指针4.1 const修饰变量4.2 const修饰指针变量…...

unity3D雨雪等粒子特效不穿透房屋效果实现(粒子不穿透模型)

做项目有时候会做天气模拟,模拟雨雪天气等等。但是容易忽略一个问题,就是房屋内不应该下雨或者下雪,这样不就穿帮了嘛。 下面就粒子穿透物体问题做一个demo。 正常下雨下雪在室内的话,你可以看到,粒子是穿透建筑的。 那要怎么模拟真实的雨雪天气,不让粒子穿透房屋建筑呢…...

ROS2安装cartographer

2. 安装Cartographer和Cartographer ROS 使用apt安装&#xff08;推荐&#xff09;&#xff1a; bash sudo apt install ros-humble-cartographer-ros或者&#xff0c;从源代码安装&#xff1a; bash sudo apt-get update sudo apt-get install -y python3-wstool python3…...

kafka测试

1】确认 ZooKeeper 服务状态 为了进一步确认 ZooKeeper 服务的状态&#xff0c;你可以执行以下操作&#xff1a; 检查 ZooKeeper 服务状态&#xff1a; docker ps 确保 ZooKeeper 容器正在运行。 检查 ZooKeeper 日志&#xff1a; docker logs zookeeper 查看最新的日志条目&…...

总结C/C++中内存区域划分

目录 1.C/C程序内存分配主要的几个区域&#xff1a; 2.内存分布图 1.C/C程序内存分配主要的几个区域&#xff1a; 1、栈区 2、堆区 3、数据段&#xff08;静态区&#xff09; 4.代码段 2.内存分布图 如图&#xff1a; static修饰静态变量成员——放在静态区 int globalVar 是…...

第168天:应急响应-ELK 日志分析系统Yara规则样本识别特征提取规则编写

目录 案例一&#xff1a;ELK 搭建使用-导入文件&监控日志&语法筛选 案例二&#xff1a;Yara 规则使用-规则检测&分析特征&自写规则 案例一&#xff1a;ELK 搭建使用-导入文件&监控日志&语法筛选 该软件是专业分析日志的工具&#xff0c;但是不支持安…...

丹东 建设集团 招聘信息网站/邢台网站网页设计

前言 CSS确实很重要&#xff0c;且有点奇技淫巧&#xff0c;看起来规则十分简单&#xff0c;但是创意更重要&#xff0c;如何用css构造出自己想要的效果&#xff0c;写的代码好看优雅十分重要。 在看了不借助Echarts等图形框架原生JS快速实现折线图效果并自己重新实现了以后&am…...

网站301跳转怎么做/现在网络推广方式

buuctf [Nginx]parsing_vulnerability_Fatesec的博客-CSDN博客Nginx 解析漏洞描nginx解析漏洞因为用户配置不当造成的漏洞。解析格式&#xff1a;1.jpg/.php、1.jpg/.php&#xff0c;1.jpg会被当成php格式解析nginx和iis7.x解析漏洞类似&#xff0c;都是加上/.php后文件以php格…...

做网站的的价位/排名优化价格

《北航计算机软件技术基础实验报告实验报告4-2——数据库应用系统的开发》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《北航计算机软件技术基础实验报告实验报告4-2——数据库应用系统的开发(10页珍藏版)》请在人人文库网上搜索。1、实验报告实验名称 数据库应用系…...

泉州专业网站建设哪家好/网站建设需要多少钱?

本发明涉及无线传感器网络领域&#xff0c;属于leach路由通信技术领域&#xff1a;。背景技术&#xff1a;&#xff1a;物联网技术飞速发展&#xff0c;无线传感器网络(wirelesssensornetworks&#xff0c;wsn)也逐渐成为互联网研究领域的热门话题&#xff0c;主要包含汇聚节点…...

css 网站 实例/企业网站制作方案

Shell执行流程 1.Printthe info of reminding 打印提示信息 2.Waitinguser for input(wait) 等待用户输入 3.Acceptthe command 接受命令 4.Interpretthe command 解释命令 5.Findit,execute it, if have the parameter, the command interprete it 找到该命令&#xff0c;执行…...

服务器搭建网站视频教程/合肥seo公司

题目链接 这里的n很大10{100}&#xff0c;数字十分大不能使用int、double等类型存储&#xff0c;需要使用字符串存储。 统计数字每位数上数字的和&#xff0c;再对于位数数字和转化为文字拼音。 #include <stdio.h> #include<string.h> int main(){char a[1002];…...