C++第一弹 -- C++基础语法上(命名空间 输入输出 缺省参数 函数重载 引用)

目录

  • 前言
  • 一. C++关键字(C++98)
  • 二. 命名空间
    • 1.命名空间的定义
    • 2.命名空间的使用
    • 3.其它部分
  • 三. C++输入&输出
  • 四. 缺省参数
    • 1. 缺省参数的概念
    • 2.缺省参数的分类
  • 五. 函数重载
    • 1.函数重载的概念
    • 2. 为什么C++支持函数重载, 而C语言不支持重载呢?
  • 六. 引用
    • 1.引用的概念
    • 2.引用的特性
    • 3.常引用
    • 4.引用场景
    • 5.引用和指针的区别

前言

C++是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式等。熟悉C语言之后,对C++学习有一定的帮助,本篇将介绍C++是如何对C语言设计不合理的地方进行优化的,比如:作用域方面、IO方面、函数方面、指针方面、宏方面等, 为后续类和对象学习打基础

更多好文点击 博客主页: 酷酷学!!! 期待您的关注!


正文开始

一. C++关键字(C++98)

C++总计63个关键字,C语言32个关键字

ps:下面我们只是看一下C++有多少关键字,不对关键字进行具体的讲解。后面我们学到以后再细讲。

在这里插入图片描述

二. 命名空间

在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域或者局部作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染namespace关键字的出现就是针对这种问题的。

使用命名空间也可以很好的解决我们和库之间或者多个程序员在进行一个项目时, 名称重复的问题, 如下面这个例子

#include<stdio.h>
#include<stdlib.h>int rand = 10;int main()
{printf("%d\n", rand);return 0;
}

这里会报错, 因为rand已经在<stdlib.h>头文件中定义过, 所以再次定义全局变量rand, 作用域都是全局, 会导致名称重复, C语言没办法解决类似这样的命名冲突问题,所以C++提出了namespace来解决.

在这里插入图片描述

编译后后报错:error C2365: “rand”: 重定义;以前的定义是“函数”

1.命名空间的定义

定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。

注意: 这里和结构体的区别在于结构体{}后有; 而命名空间没有

  1. 正常的命名空间的定义

命名空间可以定义变量/函数/类型

#include<stdio.h>
#include<stdlib.h>//int rand = 10;namespace kkx
{int rand = 10;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}int main()
{//int rand = 20;printf("%d\n", kkx::rand);return 0;
}
  1. 命名空间可以嵌套
//test.cpp
namespace N1
{int a;int b;int Add(int left, int right){return left + right;}namespace N2{int c;int d;int Sub(int left, int right){return left - right;}}
}
  1. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中.

PS:一个工程中的test.h和上面的test.cpp中两个N1会被合并成一个

//test.h
namespace N1
{int Mul(int left, int right){return left * right;}
}

2.命名空间的使用

命名空间中成员该如何使用呢?比如:

namespace N
{int a = 10;int b = 1;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}int main()
{printf("%d\n", a);return 0;
}
// 编译报错:error C2065: “a”: 未声明的标识符

编译默认查找
a、当前局部域 : 自留地
b、全局域找 : 村子野地
不会到其他命名空间中去找

命名空间的使用有三种方式:

  • 加命名空间名称及作用域限定符
int main()
{printf("%d\n", N::a);return 0;    
}
  • 使用using将命名空间中某个成员引入
using N::b;
int main()
{printf("%d\n", N::a);printf("%d\n", b);return 0;    
}
  • 使用using namespace 命名空间名称 引入

编译默认查找
/a、当前局部域 : 自留地
b、全局域找 : 村子野地
c、到展开的命名空间中查找 : 相当于张大爷在自己的自留地加了声明,谁需要就来摘

using namespce N;
int main()
{printf("%d\n", N::a);printf("%d\n", b);Add(10, 20);return 0;    
}

3.其它部分

  • 不同域中可以存在同名的变量, 编译器默认会使用局部变量, 但是如果想使用全局变量时, 不写空间名称直接写作用域限定符即表示访问全局变量
int rand = 10;
int main()
{int rand = 20;printf("%d\n", ::rand);return 0;
}
  • 使用using namespace固然好用, 但不宜过度用, 不同命名空间中有相同的名称, 全部展开, 编译器会报错,例如

namespace N1
{int a = 10;int b = 1;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}
namespace N2
{int a = 10;int b = 1;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}
using namespace N1;
using namespace N2;

三. C++输入&输出

C++的输入输出需要包含头文件 < isotream > , 直接使用cout(console out 从控制台输出) 和 endl(end line 换行) 会发生报错, 这是因为官方为避免与我们自己定义的名称和库重复, 所以将库的函数名称包含在了std命名空间里面, 所以我们如果使用需要按照命名空间的使用方法使用std

#include<iostream>int main()
{cout << "Hello World!!!" << endl;return 0;
}

在这里插入图片描述

正确用法:

#include<iostream>
// std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
using namespace std;
int main()
{cout<<"Hello world!!!"<<endl;return 0;
}//或者#include<iostream>
// std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
using std::cout;
using std::endl;
int main()
{cout<<"Hello world!!!"<<endl;return 0;
}

说明:

  1. 使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含< iostream >头文件以及按命名空间使用方法使用std。
  2. cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含< iostream >头文件中。
  3. <<是流插入运算符,>>是流提取运算符。
  4. 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。C++的输入输出可以自动识别变量类型。
  5. 实际上cout和cin分别是ostream和istream类型的对象,>>和<<也涉及运算符重载等知识,这些知识我们我们后续才会学习,所以我们这里只是简单学习他们的使用。后面我们还有有一个章节更深入的学习IO流用法及原理。

注意:早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应头文件即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间,规定C++头文件不带.h;旧编译器(vc 6.0)中还支持<iostream.h>格式,后续编译器已不支持,因此推荐使用+std的方式。

#include <iostream>
using namespace std;int main()
{int a;double b;char c;// 可以自动识别变量的类型cin >> a;cin >> b >> c;cout << a << endl;cout << b << " " << c << endl;return 0;
}

ps:关于cout和cin还有很多更复杂的用法,比如控制浮点数输出精度,控制整形输出进制格式等等。因为C++兼容C语言的用法,这些又用得不是很多,我们这里就不展开学习了。后续如果有需要,我们再配合文档学习

std命名空间的使用惯例:
std是C++标准库的命名空间,如何展开std使用更合理呢?

  1. 在日常练习中,建议直接using namespace std即可,这样就很方便。
  2. using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 + using std::cout展开常用的库对象/类型等方式。

四. 缺省参数

1. 缺省参数的概念

缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。

void Func(int a = 0)
{cout << a << endl;
}int main()
{Func();// 没有传参时,使用参数的默认值Func(10);// 传参时,使用指定的实参return 0;
}

2.缺省参数的分类

  • 全缺省参数
 void Func(int a = 10, int b = 20, int c = 30){cout<<"a = "<<a<<endl;cout<<"b = "<<b<<endl;cout<<"c = "<<c<<endl;}
  • 半缺省参数
 void Func(int a, int b = 10, int c = 20){cout<<"a = "<<a<<endl;cout<<"b = "<<b<<endl;cout<<"c = "<<c<<endl;}

传值时只能顺序传,不能跳着传

int main()
{F2(1, 2, 3);F2(1, 2);F2(1);F2();// 必须顺序传,不能跳跃着传// F2(1, ,2);

注意:

  1. 半缺省参数必须从右往左依次来给出,不能间隔着给
  2. 缺省参数不能在函数声明和定义中同时出现, 如果缺省参数的声明和定义分离, 以声明的值为主.
  //a.hvoid Func(int a = 10);// a.cppvoid Func(int a = 20){}// 注意:注意:如果生命与定义位置同时出现,以声明为主
  1. 缺省值必须是常量或者全局变量
  2. C语言不支持(编译器不支持)

五. 函数重载

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。
比如:以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了!”,后者是“谁也赢不了!”

1.函数重载的概念

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数类型类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。

即同一作用域, 参数个数不同, 参数类型不同, 类型顺序不同, 三种情况构造重载关系

#include<iostream>
using namespace std;//1.参数类型不同
int Add(int left, int right)
{cout << "int Add(int left, int right)" << endl;return left + right;
}double Add(double left, double right)
{cout << "double Add(double left, double right)" << endl;return left + right;
}//2.参数个数不同void f()
{cout << "f()" << endl;
}
void f(int a)
{cout << "void f(int a)" << endl;
}//3.参数类型顺序不同void f(int a, char b)
{cout << "void f(int a, char b)" << endl;
}void f(char a, int b)
{cout << "void f(char a, int b)" << endl;
}int main()
{Add(10, 20);Add(10.1, 20.2);f();f(10);f(10, 'a');f('a', 10);return 0;
}

不同作用域, 可以同名
同一作用域, 可以同名, 满足重载规则

 //不同作用域 可以同名
namespace N1
{void Swap(int* pa, int* pb){cout << "void Swap(int* pa, int* pb)" << endl;}
}namespace N2
{void Swap(int* px, int* py){cout << "void Swap(int* pa, int* pb)" << endl;}
}// 同一作用域 可以同名,满足重载规则
void Swap(double* pa, double* pb)
{cout << "void Swap(double* pa, double* pb)" << endl;
}using namespace N1;
using namespace N2;
// 他们两依旧是ok,不是重载关系int main()
{int a = 0, b = 1;double c = 0.1, d = 1.1;// 调用歧义//Swap(&a, &b);Swap(&c, &d);return 0;
}

这段代码N1, N2 不在同一作用域, 可以同名, 不构成重载, 但是命名空间全部展开, 会引发调用歧义.

下面两个构造函数重载
f()但是这样调用存在歧义

void f()
{cout << "f()" << endl;
}void f(int a = 10)
{cout << "f(int a)" << endl;
}

2. 为什么C++支持函数重载, 而C语言不支持重载呢?

这是因为在函数定义与声明分离时, 编译阶段无法直接获得函数地址, 只是通过函数声明,语法可以通过, 链接阶段, C语言直接通过函数名字进行查找, 不支持函数重载, 而C++是使用修饰后的函数名字去查找就可以支持函数重载.

具体过程如下:

  1. 一个项目工程中, 声明和定义通常是分离的, 声明在.h文件中, 定义在.cpp文件中, 如下图
    在这里插入图片描述
    代码在变成可执行程序需要经过编译和链接, 编译分为三个过程, 首先经过预处理, 将.h与.cpp文件进行结合, 进行头文件展开, 宏替换, 条件编译等等, 生成.i文件, 此时就没有.h文件的事情了. 然后, 通过编译, 检查语法, 生成汇编代码, 此时语法通过, 检查语法匹配, 但没有函数地址. 最后通过汇编转成二进制机械码, 但是有函数的定义, 才能生成一堆汇编指令, 所以在链接阶段, 需要查找函数地址, 也就是将Test.o和Stack.o链接在一起.

在这里插入图片描述
如图所示, 转成汇编代码, 在调用StackInit()函数时, 语法通过, 然后执行下一句, jmp指令会通过StackInit()函数名去查找函数地址
在这里插入图片描述
函数有一对要执行的指令, 函数地址就是第一句指令的地址.
在这里插入图片描述
那么,也就是说在声明与定义分离时, 链接过程中需要通过函数名字去找函数地址, 而C语言直接使用函数名字查找,不支持重载, 而C++使用过修饰后的名字查找, 支持重载.

如下图, 我们先将函数定义注释, 就可以看到, 发上了链接错误, 此时我们再看如何进行修饰的, Windows平台下, C++会根据参数列表(参数个数 或 类型 或 类型顺序) 进行函数名字的修饰, 函数重载, 修饰出来的名字不一样, 那就可以区分. 而C语言则没有对函数名字进行修饰

在这里插入图片描述

不同从操作系统对函数名字的修饰规则也不太一样, 比如在Linux操作系统下,对这三个函数的修饰就很直观, 以首字母进行修饰

在这里插入图片描述

在这里插入图片描述
而我们将文件改成.c 就可以发现C语言没有对函数名字修饰, 所以不支持重载

在这里插入图片描述

对比Linux会发现,windows下vs编译器对函数名字修饰规则相对复杂难懂,但道理都是类似的,我们就不做细致的研究了。

六. 引用

1.引用的概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
比如:李逵,在家称为"铁牛",江湖上人称"黑旋风"。

在这里插入图片描述

类型& 引用变量名(对象名) = 引用实体;

void TestRef()
{int a = 10;int& ra = a; //定义引用类型printf("%p\n", &a);printf("%p\n", &ra);}
int main()
{TestRef();return 0;
}

在这里插入图片描述
注意: 引用类型必须和引用实体是同种类型的

2.引用的特性

  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体, 再不引用其它实体
void TestRef()
{int a = 10;int& ra = a;//<====定义引用类型printf("%p\n", &a);printf("%p\n", &ra);
}

3.常引用

void TestConstRef()
{const int a = 10;//int& ra = a;   // 该语句编译时会出错,a为常量const int& ra = a;// int& b = 10; // 该语句编译时会出错,b为常量const int& b = 10;double d = 12.34;//int& rd = d; // 该语句编译时会出错,类型不同const int& rd = d;
}

4.引用场景

  1. 做参数

之前我们在另一个函数交换值需要传地址, 有了引用就可以直接传引用,此时left就相当于a的别名, 而right就相当于b的别名.

void Swap(int& left, int& right)
{int temp = left;left = right;right = temp;
}int main()
{int a = 10;int b = 20;Swap(a,b);return 0;
}
  1. 做返回值

后面我们在细讲

5.引用和指针的区别

typedef struct ListNode
{int val;struct ListNode* next;
}LTNode;//之前我们不带哨兵位的链表插入结点需要传递二级指针
void ListPushBack(LTNode** phead, int x);//这里也可以传递phead指针的引用
void ListPushBack(LTNode*& phead, int x);//有的教材还可能这样写
typedef struct ListNode
{int val;struct ListNode* next;
}LTNode, * PNode;
//其本质也是一样的,只是将struct ListNode* 类型重命名为PNode
void ListPushBack(PNode& phead, int x);

这段代码, 是将z赋值给y, 因为引用一旦引用实体,就不可以引用别的实体

int main()
{// int& a;int x = 0;int& y = x;int z = 1;// y变成z的别名呢?// 还是z赋值给yy = z;return 0;
}

不管是引用普通变量还是指针变量, 只能权限的缩小, 而不能权限的放大 ,指针赋值也是, 因为被const修饰的地址不可以修改

int main(){int x = 0;int& y = x; //权限的平移,可以const int& z = x;//权限的缩小,可以y++;//可以,z++不可以const int m = 0;// int& n = m;m是只读的,n变成我的别名,n的权限是可读可写,权限的放大,不可以const int& n = m; //可以,不是权限的放大int p = m;// m拷贝的给p,p的修改不影响m// 权限的放大// p1可以修改 *p1不可以,const修饰是的*p1const int* p1 = &m;// p1++;// int* p2 = p1;//不可以,p1的内容不可以修改const int* p2 = p1;//可以,常量赋值给常量// 权限的缩小,可以int* p3 = &x;const int* p4 = p3;return 0;
}

在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。
在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。

引用和指针的不同点:

  1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
  2. 引用在定义时必须初始化,指针没有要求
  3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
  4. 没有NULL引用,但有NULL指针
  5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
  6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
    int main()
    {
    int a = 10;
    int& ra = a;
    cout<<"&a = “<<&a<<endl;
    cout<<”&ra = "<<&ra<<endl;
    return 0;
    }
    int main()
    {
    int a = 10;
    int& ra = a;
    ra = 20;
    int* pa = &a;
    *pa = 20;
    return 0;
    }
  7. 有多级指针,但是没有多级引用
  8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
  9. 引用比指针使用起来相对更安全

感谢点赞, 关注, 收藏!!!

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

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

相关文章

通过AIS实现船舶追踪与照射

前些天突然接到个紧急的项目&#xff1a;某处需要实现对夜航船只进行追踪并用激光灯照射以保障夜航安全。这个项目紧急到什么程度呢&#xff1f;&#xff01;现场激光灯都安装好了&#xff0c;还有三个星期就要验收了&#xff0c;但上家没搞定就甩给我们了:( 从技术上看&#…

Java应用系统设计与实现--学生信息管理系统(附解决方案源码)

一、实验目的及要求 1.1实验目的 掌握Java GUI编程技术&#xff0c;了解Swing框架的使用。 掌握MySQL数据库的基本操作&#xff0c;了解如何在Java中连接和操作数据库。 掌握用户权限管理的基本概念和实现方法。 提升综合运用所学知识设计和实现一个完整应用系统的能力…

windows机器免密登录linux主机

1. 正常连接需要输入密码 ssh root1.1.1.1 2. 在Windows上生成SSH密钥对&#xff08;如果你还没有的话&#xff09;&#xff1a; ssh-keygen 3. scp将id_rsa.pub传输到对应的主机 4.对应机器上查看 5.从windows上免密登录

ESP32 蓝牙网关实践:BLE 设备数据采集与 MQTT 云平台发布(附代码示例)

摘要: 本文详细介绍了如何使用 ESP32 构建强大的蓝牙网关&#xff0c;实现蓝牙设备与 Wi-Fi/互联网之间的无缝连接和数据桥接。文章涵盖了连接和桥接功能、数据处理和分析能力&#xff0c;并提供了详细的代码示例和 Mermaid 生成的图表&#xff0c;助您轻松构建自己的蓝牙网关解…

树(相关知识点)

目录 结点的度&#xff1a;某一个结点所含有字数的个数 叶节点&#xff1a;最后一个结点 非终端节点:不是叶结点 兄弟结点&#xff1a;亲兄弟结点 树的度&#xff1a;最大节点的度 层次&#xff1a;根为第一层&#xff0c;根的子结点为第二层&#xff0c;以此类推 森林&am…

微软拼音输入法不显示选字框问题

问题展示&#xff1a;不显示选字框 解决方式 打开兼容性即可&#xff08;估计是升级带来的bug&#xff09;

Android使用http加载自建服务器静态网页

最终效果如下图&#xff0c;成功加载了电脑端的静态网页内容&#xff0c;这是一个xml文件。 电脑端搭建http服务器 使用“Apache Http Server”&#xff0c;下载地址是&#xff1a;https://httpd.apache.org/download.cgi。具体操作步骤&#xff0c;参考&#xff1a;Apache …

深度学习与CV入门

文章目录 前言历史 前言 历史 tensorflow可以安装Tensorboard第三方库用于展示效果 TensorFlow工作流程&#xff1a;p6-4:20 使用tf.data加载数据。使用tf.data实例化读取训练数据和测试数据模型的建立与调试:使用动态图模式Eager Execution和著名的神经网络高层API框架Ker…

关于忠诚:忠于自己的良知、理想、信念

关于忠诚&#xff1a; 当我们面对公司、上司、爱人、恋人、合作伙伴还是某件事&#xff0c;会纠结离开还是留下&#xff0c;这里我们要深知忠诚的定义&#xff0c;我们不是忠诚于某个人、某件事、或者某个机构&#xff0c;而是忠诚于自己的良知&#xff0c;忠诚于自己的理想和…

1.1 常用文件管理命令

文章目录 前言正式学习文件系统常用的指令总结 前言 现在自己想做一个简单的编译器&#xff0c;但是安装环境就感觉非常难受&#xff0c;反正 linux 也是必须要学的&#xff0c;虽然&#xff0c;非常紧迫&#xff0c;但是很多事情着急也没有用&#xff0c;所以&#xff0c;现在…

ctfshow-web入门-文件上传(web151-web160)

目录 1、web151 2、web152 3、web153 4、web154 5、web155 6、web156 7、web157 8、web158 9、web159 10、web160 1、web151 试了下前端只能传 png 后缀的 将一句话木马改成 png 后缀&#xff0c;上传后用 burpsuite 抓包 绕过前端检测后&#xff0c;改回 php 后缀&am…

阶段三:项目开发---搭建项目前后端系统基础架构:任务11:搭建项目后台系统基础架构

任务描述 1、了解搭建民航后端框架 2、使用IDEA创建基于SpringBoot、MyBatis、MySQL、Redis的Java项目 3、以原项目为参照搭建项目所涉及到的各个业务和底层服务 4、以原项目为例&#xff0c;具体介绍各个目录情况并参照创建相关文件夹 任务指导 1、讲框架的选择和原理 …

《梦醒蝶飞:释放Excel函数与公式的力量》9.4 NPV函数

9.4 NPV函数 NPV函数是Excel中用于计算净现值的函数。净现值&#xff08;Net Present Value, NPV&#xff09;是财务管理和投资决策中常用的指标&#xff0c;用于评估投资项目的价值。NPV表示的是未来一系列现金流的现值总和减去初始投资后的余额。 9.4.1 函数简介 NPV函数通…

微信小程序订单发货管理接入

订单发货管理接入指引&#xff1a;https://mp.weixin.qq.com/cgi-bin/announce?token1148555877&actiongetannouncement&key11671435333v04b2&version1&langzh_CN&platform2https://mp.weixin.qq.com/cgi-bin/announce?token1148555877&actiongetann…

32位Arm嵌入式开发Ubuntu环境设置

32位Arm嵌入式开发Ubuntu环境设置 今天在调试一块32位ARM A7开发板时老是不成功&#xff0c;我装的是Ubuntu22.04版&#xff0c;在终端下运行工具链里的gdb程序居然报了一大堆错误&#xff0c;缺这个缺那个&#xff0c;按照提示装了一遍&#xff0c;再运行发现需要Python2.7环境…

【机器学习】基于密度的聚类算法:DBSCAN详解

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 基于密度的聚类算法&#xff1a;DBSCAN详解引言DBSCAN的基本概念点的分类聚类过…

QThread moveToThread的妙用

官方文档描述 总结就是移动到线程的对象不能有父对象&#xff0c;执行start即起一个线程&#xff0c;示例是将myObject移动到主线程中。QT中这种方式起一个线程是非常简单的。 示例描述以及代码 描述往Communicate线程中频繁添加任务&#xff0c;等任务结束的时候统计计算的结…

001,函数指针是一种特殊的指针,它指向的是一个函数地址,可以存储函数并作为参数传递,也可以用于动态绑定和回调函数

函数指针是一种特殊的指针 001&#xff0c;函数指针是一种特殊的指针&#xff0c;它指向的是一个函数地址&#xff0c;可以存储函数并作为参数传递&#xff0c;也可以用于动态绑定和回调函数 文章目录 函数指针是一种特殊的指针前言总结 前言 这是ai回答的标准答案 下面我们…

如何监控和分析 PostgreSQL 中的查询执行计划?

文章目录 一、为什么监控和分析查询执行计划很重要二、PostgreSQL 中用于获取查询执行计划的方法三、理解查询执行计划的关键元素四、通过示例分析查询执行计划五、优化查询执行计划的常见策略六、使用工具辅助分析七、结合实际案例的详细分析八、总结 在 PostgreSQL 数据库中&…

[LoaderRunner] 关于LoaderRunner的基本使用

LoadRunner环境搭建 LoadRunner运行的环境参考以下文档&#xff1a;Docs 介绍LoadRunner LoadRunner是什么 LoadRunner是性能测试工具&#xff0c;对软件或者系统的性能进行评估 为什么使用LoadRunner LoadRunner具有以下的优势&#xff1a; LoadRunner相比于其他的测试工具…