[C/C++]指针详讲-让你不在害怕指针
- 个人主页:北·海
- 🎐CSDN新晋作者
- 🎉欢迎 👍点赞✍评论⭐收藏
- ✨收录专栏:C/C++
- 🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!🤗
目录
前言
一.&与*的作用与结合方向
二.指针和数组的关系
1.利用指针访问数组里的值
2.利用指针将数组作为实参传递给函数
三.字符指针与字符数组
四.指针在内存分配中的应用
1.用C语言中的malloc在堆区分配动态内存
1.用C++中的new在堆区分配动态内存
五.使用指针为什么能提高程序的性能
六.指针与const搭配的四种情况
七.引用是实现原理
八.多级指针
九. 指针和函数的关系
1.通过指针使函数返回多个值
2.函数指针
3.函数的返回值类型为指针类型
十.指针和结构体的关系
前言
指针在编程语言中扮演着重要的角色,特别是在C语言中。指针提供了直接访问和操作内存地址的能力,使得编程更加灵活、高效,并且可以处理各种复杂的数据结构和算法。
以下是指针的几个重要方面和作用:
内存管理:指针允许程序直接与内存交互。通过使用指针,可以动态地分配和释放内存,避免了静态内存分配所带来的限制。这在处理动态数据结构(如链表、树、图等)和大规模数据中非常有用。
传递参数和引用:通过指针,可以在函数之间传递参数和引用。传递指针作为函数参数,可以避免在函数调用时产生副本,节省了内存和时间开销。此外,指针还可以用于函数返回多个值或修改调用者的变量。
动态数据结构:动态数据结构如链表、树、堆等通常需要使用指针进行内存分配和组织。指针可以在运行时创建、删除、连接和重新组织数据结构,使得数据结构的管理更加灵活和高效。
数组和字符串操作:在C语言中,数组实际上是通过指针来访问和操作的。指针使得数组可以直接访问和修改其元素,还可以进行指针算术操作,实现数组的遍历和操作。字符串在C语言中本质上是以空字符结尾的字符数组,指针的使用是对字符串进行处理的关键。
性能优化:指针的使用可以提高程序的性能。通过使用指针来访问和操作数据,可以减少副本的生成和数据的复制,提高程序的执行效率。
一.&与*的作用与结合方向
作用: &在等号的右边为取地址符号,在等号的左边为引用符号
*可以用做为乘号,也可用作为对指针变量解引的符号,取该地址存放的数据
结合方向:
“&”和“*”都是右结合的。假设有变量 x = 1,则*&x 的含义是,先获取变量 x 的地址,再获取地址中的内容。因为“&”和“*”互为逆运算,所以 x = *&x。
例如:输入 x、y 两个整数,然后将其中的值大的赋值给 x,小的赋值给 y。即:假设输入 x = 8,y = 9。就将 9 赋值给 x,8 赋值给 y。
void main(){//声明两个普通变量int x, y;//声明两个指针变量int *px, *py;//声明一个临时变量,用于交换int t;//输入两个值,赋值给 x、yscanf("%d", &x);scanf("%d", &y);//给指针变量 px、py 赋初值(关联变量 x、y)px = &x;py = &y;//利用指针来对比 x、y 的值,如果 x 的值比 y 的值小,就交换if(*px < *py){//交换步骤,其中*px == x、*py == yt = *px;*px = *py;*py = t;}printf("x = %d, y = %d", *px, *py); }
二.指针和数组的关系
1.利用指针访问数组里的值
//利用指针访问数组里面的值int nums[] = {1,2,3,4};//方法一:下标法cout << "第一个数 :" << nums[0] << endl;//方法二:指针法cout << "第一个数 :" << *(nums + 0) << endl;//数组名就是数组元素的首地址
2.利用指针将数组作为实参传递给函数
void Test1(int nums[],int n) {for (int i = 0; i < n; i++) {cout << nums[i] << " ";} }int main() {//利用指针访问数组里面的值int nums[] = {1,2,3,4};int* p = nums;//利用指针将数组作为实参传递给函数Test1(nums, 4);//数组名就是数组元素的首地址//方法二Test1(p, 4);//p指向数组,再将指向数组的指针传给被调函数 }
补充对指针加一 : 例如p++,不会将地址的值加一,而是将数组下移一位
三.字符指针与字符数组
C语言中,没有字符串类型的变量,通常用字符数组或者字符指针存放字符串
1.字符数组的声明
char str[] = "C++";char str1[] = { 'C','+','+' ,'\0'};字符数组的声明方式,在使用第二种声明方式的时候,必须在最后加上\0,此符号代表在这个地方该数组就结束了,如果不加该符号,会访问出界的
字符数组的访问
char str[] = "C++";char str1[] = { 'C','+','+' ,'\0'};printf("%s\n", str1);//%s格式化,表示直接输出整个数组printf("%c\n", str[0]);//利用数组法取str第一个字符printf("%c\n", *(str1 + 1));//利用指针法取str1的第2个字符
由上面可以看出,可以通过%c一个字符一个字符的输出,那么也可也利用循环输出每个字符
for (int i = 0; i < strlen(str); i++) {printf("%c", str[i]);}
还可以用过strlen(str)或者sizeof(str)/sizeof(char)来获取该数组的长度
2.字符指针的声明
char *word = "have a good night";
字符指针的访问
const char* word = "have a good night";printf("%s\n", word);printf("%c\n", word[0]);for (int i = 0; i < strlen(word); i++) {printf("%c", word[i]);}
对字符指针地址的加减
const char* word = "have a good night";word++;printf("%s\n", word);//此时就会将指针下移到第一个a的地方,从a的地方进行输出,输出为:ave a good nightword--;printf("%s\n", word);//输出为:have a good nightconst char str[] = "C++";str++;//报错,在字符数组中不能进行加减操作,表达式必须是可修改的左值printf("%s", str);
四.指针在内存分配中的应用
1.用C语言中的malloc在堆区分配动态内存
1.利用malloc创建一维数组
#include <iostream> #include <stdlib.h> using namespace std; int main() {int n;int* p = nullptr;cout << "请输入要存放的数据个数:";cin >> n;//在堆区分配内存p = (int *)malloc(n * sizeof(int));//输入for (int i = 0; i < n; i++) {cin >> *(p+i);}//输出for (int i = 0; i < n; i++) {cout << *(p+i) << " ";}free(p); }
用malloc进行分配,注意malloc的返回值类型位void*类型,需要进行强制类型转换,由于在堆区分配的动态内存,所以在使用完之后,为了防止内存泄漏,需要用free进行释放
2.利用malloc进行开辟二位数组,与释放二位数组
#include <iostream> #include <stdlib.h> using namespace std; int main() {int row = 0 ,col = 0 ;int** p = nullptr;cout << "依此输入行和列:" << endl;cin >> row>>col;//在堆区分配内存p = (int **)malloc(row * sizeof(int*));for (int i = 0; i < row; i++) {*(p + i) = (int*)malloc(col * sizeof(int));}//输入for (int i = 0; i < row * col; i++) {cin >> p[i / col][i % col];}//输出for (int i = 0; i < row * col; i++) {cout << p[i / col][i % col] << " ";}//释放动态开辟的二维数组for (int i = 0; i < row; i++) {free(p[i]);}free(p); }
原理是,先创建一个指针数组,然后在利用改一级指针去创建动态int类型数组,在输入时候,用到了一个小技巧,用一层循环给二维数组赋值,在使用二维数组时候,应该先将每一层一级指针指向的内存块释放掉,然后再去释放该释放二级指针本身指向的内存块
1.用C++中的new在堆区分配动态内存
用到C++中的new分配内存,用delete释放内存,这里的new和delete只适用于c++中,malloc与free适用于c/c++,直接上例子
1.使用new进行分配一个动态的一维数组
int main() {int n;cout << "输入数组的大小:";cin >> n;int* p = new int[n];//输入for (int i = 0; i < n; i++) {cin >> *(p + i);}//输出for (int i = 0; i < n; i++) {cout << *(p + i) << " ";}delete[]p; }
2.创建二维数组
int main() {int rows = 3;int cols = 4;// 创建动态二维数组int** array = new int*[rows]; // 创建一级指针数组for (int i = 0; i < rows; i++) {array[i] = new int[cols]; // 创建二级指针数组}// 使用动态二维数组for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {array[i][j] = i * cols + j; // 给数组元素赋值}}// 打印动态二维数组for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {std::cout << array[i][j] << " ";}std::cout << std::endl;}// 释放动态二维数组的内存for (int i = 0; i < rows; i++) {delete[] array[i]; // 释放二级指针数组}delete[] array; // 释放一级指针数组return 0; }
和malloc的原理都是一样的,起始可以将一维数组创建的长一点,利用p[i / col][i % col];完全可以将一位数组当二维数组用,二维数组的存储方式也是按行存储的,地址都是连续的
在使用delete时候,数组的释放格式为 delete []p;,单个变量的释放格式为 delete p;
五.使用指针为什么能提高程序的性能
-
直接访问内存:指针允许直接访问和操作内存中的数据。相比于通过变量的拷贝进行操作,直接访问内存可以减少数据的复制和移动,从而提高程序的执行效率。
#include <iostream> using namespace std; void Test1(int *p) {(*p)++; } void Test2(int m) {m++; } int main() {int num1 = 10,num2=10;Test1(&num1);cout << "Test1 :" << num1 << endl;//输出结果11Test2(num2);cout << "Test2 :" << num2 << endl;//输出结果10 }
Test1通过直接访问内存,避免了数据的拷贝和移动,提高了程序的执行效率。
Test2函数通过传递值的拷贝来操作变量。当我们调用该函数后,原始变量的值保持不变
-
减少内存和时间开销:通过传递指针作为函数参数,可以避免在函数调用时产生变量的副本,从而减少内存的使用和传输的时间开销。特别是在处理大型数据结构或大量数据时,使用指针可以显著减少内存和时间的消耗。
-
动态内存分配:指针使得动态内存分配成为可能,即在程序运行时根据需要分配和释放内存。相比于静态内存分配,动态内存分配可以更灵活地管理内存,避免内存浪费和限制,并且减少了程序启动时的内存占用。
六.指针与const搭配的四种情况
- const 写在int之前,则限定不能通过*指针去改变该指针指向的值,但是可以指向别的指针
- const 写在int之后,则限定可以通过*指针去改变该指针指向的值,但是不能指向别的指针
- 两个const一个写在int前,一个写在变量名前,限制指针不能指向别的指针,并且不允许修改指针指向的值
- 总结 : 看const离类型(int)近,还是理变量名近,离谁近,就修饰谁,谁就不能变
#include<iostream> using namespace std;int main() {int wife = 30;int girl = 18;//第一种 : 渣男型,普通指针可以随意更改指向与指向地址的值int* zha_nan = &wife;cout << *zha_nan << endl;zha_nan = &girl;cout << *zha_nan << endl;//第二种 : 直男型,以自我为中心,可以改变指向,但是不可以改变指向的地址的值const int* zhi_nan = &wife;//*zhi_nan = 25;//报错,不能改变值zhi_nan = &girl;cout << *zhi_nan << endl;//第三种 : 暖男型,专一,不可以改变指向,但是可以改变指向的地址的值int* const nuan_nan = &wife;//nuan_nan = &girl;//报错,不能改变指向*nuan_nan = 25;cout << *nuan_nan << endl;//第四种 : 超级暖男型,超级专一,不能改变指向,也不能改变指向地址的值const int* const _super_nuan_nan = &wife;//*_super_nuan_nan = 25;//报错,不能改变指向地址的值//super_nuan_nan = &girl;//报错,不能改变指向//总结 : const理谁近就修饰谁,理(int)近,则修饰该指针的值不能改变,修饰变量,// 则该指针不能在指向别的变量了 }
七.引用是实现原理
引用的底层也是用指针进行实现的
int a = 0;int b = 2;int& c = a;c = b;//c是a的别名,将b的值赋值给c,就相当于将b的值也赋值给了acout << c << endl;//2cout << a << endl;//2//引用变量只能初始化一次,很像 int* const c = a;//该指针也只能进行一次初始化,就可以猜测引用的底层也是用该类型指针实现的
在使用引用的时候,编辑器会将引用类型转换为int * const 类型
例子:
void swap1(int& a, int& b) {int temp = a;a = b;b = temp; } void swap2(int* const a,int* const b) {int temp = *a;*a = *b;*b = temp; } int main() {int a = 1;int b = 2;swap1(a, b);//引用实现cout << "a = " << a << " b = " << b << endl;//a = 2,b =1swap2(&a, &b);cout << "a = " << a << " b = " << b << endl;//a = 2,b =1 }
对照swap1和swap2,在形参方面,引用变量会被改为int * const类型,在实参方面会将传入整数改为传入地址
八.多级指针
举例二级指针,懂了引用变量的话,那么对二级指针就可以有个优化了,提出指针引用,代码如下:
void home(int * p) {int b = 12;p = &b; } int main() {int a = 10;int* p = &a;//让p存放b的地址home(p);cout << *p << endl;//10 }
可以看出以上代码是无法改变p的指向的,改变值需要用一级指针,改变一级指针的指向需要用到二级指针,一次类推,这里直接就不写二级指针了,直接用一级指针的引用代替二级指针
void home(int *& p) {int b = 12;p = &b; } int main() {int a = 10;int* p = &a;//让p存放b的地址home(p);cout << *p << endl;//12 }
由此可以看出,利用指针引用可以将p的指向改变,这也的引用可以增强代码的可读性,与简洁性
九. 指针和函数的关系
1.通过指针使函数返回多个值
比如给你了一个已经初始化的数组,需要定义一个函数,用于返回这个数组的最大值与次大值,这个时候,为了增强代码的可读性,尽量返回一个数组,因为当返回的数据多了,也只能用返回数组实现了,代码如下:
void _max(int *nums,int n,int* exterm) {exterm[0] = nums[0];exterm[1] = nums[0];for (int i = 0; i < n; i++) {//大于次大的if (nums[i] > exterm[1]) {if (nums[i] > exterm[0]) {//大于最大的exterm[1] = exterm[0];exterm[0] = nums[i];}if (nums[i] < exterm[0]) {//小于最大的exterm[1] = nums[i];}}} }int main() {//求该数组中的最大值与次大值int nums[] = { 2,6,4,9,5 };int exterm[2] = { 0 };_max(nums, 5, exterm);cout << exterm[0] << " " << exterm[1] << endl;//9,6 }
2.函数指针
函数指针是指向函数的指针变量。它可以存储函数的地址,并允许我们通过该指针调用相应的函数。函数指针在C和C++中都有广泛的应用,可以用于回调函数、函数参数以及实现函数的动态调用等场景。
要理解函数指针,首先需要了解函数的定义和函数指针的声明以及函数指针的使用方式。
1.函数定义: 返回类型 函数名(参数列表) {// 函数体 }2.函数指针的声明: 返回类型 (*指针变量名)(参数列表);指针变量名:函数指针的名称。 *:用于指明该变量是一个指针。 返回类型:函数指针指向的函数的返回类型。 参数列表:函数指针指向的函数的参数列表。3.将函数指针指向函数 指针变量名 = 函数名;4.通过函数指针调用函数: (*指针变量名)(参数列表);//方法一 (指针变量名)(参数列表);//方法二
举例:
#include <iostream>int add(int a, int b) {return a + b; }int subtract(int a, int b) {return a - b; }int main() {// 声明函数指针int (*p)(int, int);// 将函数指针指向add函数p = add;// 通过函数指针调用add函数int result = (*p)(10, 5);std::cout << "Add: " << result << std::endl;// 将函数指针指向subtract函数p = subtract;// 通过函数指针调用subtract函数result = (*p)(10, 5);std::cout << "Subtract: " << result << std::endl;return 0; }
3.函数的返回值类型为指针类型
int* creat() {return new int(1);//创建一个int类型的变量初始化为1,动态分配的数组不能进行初始化 }int main() {//函数的返回值类型为指针变量类型,例子,//在creat函数里面动态的分配内存,将指向该段内存的指针返回int* p = creat();cout << "*p :" << *p << endl;//*p : 1delete p; }
十.指针和结构体的关系
利用指针访问结构体里面的值
struct Test{int a;int b;int c;};struct Test ss = { 2,3,4 };//声明了结构对象ss,并把ss 的成员初始化为2,3 和4。struct Test* ptr = &ss;//声明了一个指向结构对象ss 的指针。它的类型是//Test *,它指向的类型是Test 。printf("%d", ptr->a);printf("%d", ptr->b);printf("%d", ptr->c);
相关文章:

[C/C++]指针详讲-让你不在害怕指针
个人主页:北海 🎐CSDN新晋作者 🎉欢迎 👍点赞✍评论⭐收藏✨收录专栏:C/C🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!ǹ…...

无涯教程-Android - Frame Layout函数
Frame Layout 旨在遮挡屏幕上的某个区域以显示单个项目,通常,应使用FrameLayout来保存单个子视图,因为在子视图彼此不重叠的情况下,难以以可扩展到不同屏幕尺寸的方式组织子视图。 不过,您可以使用android:layout_grav…...

docker desktop安装es 并连接elasticsearch-head:5
首先要保证docker安装成功,打开cmd,输入docker -v,出现如下界面说明安装成功了 下面开始安装es 第一步:拉取es镜像 docker pull elasticsearch:7.6.2第二步:运行容器 docker run -d --namees7 --restartalways -p 9…...

计网(第四章)(网络层)(六)
目录 一、路由选择协议(动态路由自动获取路由信息)概述: 二、因特网采用的路由协议 主要特点: 1.自适应 2.分布式 3.分层次 因特网采用分层次的路由选择协议: 三、常见的路由选择协议 一、路由选择协议ÿ…...

科研无人机平台P600进阶版,突破科研难题!
随着无人机技术日益成熟,无人机的应用领域不断扩大,对无人机研发的需求也在不断增加。然而,许多开发人员面临着无法从零开始构建无人机的时间和精力压力,同时也缺乏适合的软件平台来支持他们的开发工作。为了解决这个问题…...

Apache的简单介绍(LAMP架构+搭建Discuz论坛)
文章目录 1.Apache概述1.1什么是apache1.2 apache的功能及特性1.2.1功能1.2.2特性 1.3 MPM 工作模式1.3.1 prefork模式1.3.2 worker模式1.3.3 event模式 2.LAMP概述2.1 LAMP的组成2.2 LAMP各组件的主要作用2.3 LAMP的工作过程2.4CGI和FastCGI 3.搭建Discuz论坛所需4.编译安装Ap…...

CDL基础原理
一、CDL简介 CDL(全称Change Data Loader)是一个基于Kafka Connect框架的实时数据集成服务。 CDL服务能够从各种OLTP数据库中捕获数据库的Data Change事件,并推送到kafka,再由sink connector推送到大数据生态系统中。 CDL目前支…...

WPF基础入门-Class7-WPF-MVVN框架
WPF基础入门 Class7-MVVN框架 使用框架可以省掉如Class6中的ViewModelBase.cs的OnPropertyChanged,亦方便命令传参 1、NuGet安装CommunityToolkit.Mvvm(原Mircrosoft.Toolkit.Mvvm)也可以安装MVVMLight等其他集成库 2、显示页面࿱…...

C语言练习题第三弹!!!绝对典中典!!!
目录 1.单身狗1 1.1 题目 1.2 分析推理 1.3 代码实现 2.单身狗2 2.1 题目 2.2 分析推理 2.3 代码实现 3.字符串左旋 3.1 题目 3.2 分析推理 3.3 代码实现 3.3.1 方法一 3.3.2 优化一 3.3.2.1 思路分析 3.3.2.2 strcpy函数和strncat函数 3.3.2.3 代码实现 3.3.…...

Jedis
Jedis 使用Java操作redis Jedis是redis官方推荐的Java连接开发工具! 使用Java操作redis的中间件 测试 导入对应的依赖 <!-- https://mvnrepository.com/artifact/redis.clients/jedis --><dependency><groupId>redis.clients</groupId&g…...

Linux 使用TCP_INFO查询TCP连接的状态信息
Linux 上可以使用TCP_INFO查询TCP连接状态信息包括: 发送方拥塞窗口阈值、发送方缓冲区拥塞窗口、advmss(Advertised MSS)、通过 ACK 确认的累计字节数等等 struct tcp_info {__u8 tcpi_state;__u8 tcpi_ca_state;__u8 tcpi_retransmits;__…...

软件测试案例 | 气象探测库存管理系统的集成测试计划
将经过单元测试的模块按照设计要求连接起来,组成规定的软件系统的过程被称为“集成”。集成测试也被称为组装测试、联合测试、子系统测试或部件测试等,其主要用于检查各个软件单元之间的接口是否正确。集成测试同时也是单元测试的逻辑扩展,即…...

vue点击按钮重新加载页面(vue第一次加载页面点击按钮出现页面刷新问题之后一切正常)
问题描述 所开发的vue项目每次跑起来之后就会出现点击按钮后重新加载整个页面的问题,但是只会在第一次点击的时候出现,后面就不会在出现加载整个页面的情况。 原因 在form表单中使用button按钮导致form表单进行了页面刷新。button默认的“type‘submi…...

软件工程(十一) 系统设计分类
我们知道需求规格说明书(SRS)落地之后, 就要开始着手系统设计了,看一下这个系统该如何来设计,并且如何实现。学习系统设计之前,需要先了解系统设计有哪些分类。 系统设计的分类如下 界面设计结构化设计面向对象设计(最重要)1、界面设计 界面设计也叫做人机界面设计,属于…...

数字转中文大写金额
有时候,我们需要显示中文大写金额,比如打印银行付款申请单等。 新建一个工程,加入一个标准模块在模块中加入如下代码,窗口中调用 AmountInChineseWords 函数即可。最大解析到百万亿,小数最多解析两位到分。 模块代码…...

Java——HashMap和HashTable的区别
Java——HashMap和HashTable的区别 Java HashMap和HashTable的区别1. 继承的父类2. 线程安全性3. null值问题4. 初始容量及扩容方式5. 遍历方式6. 计算hash值方式 Java HashMap和HashTable的区别 1. 继承的父类 都实现了Map、Cloneable(可复制)、Seria…...

Docker去除sudo权限
Docker去除sudo权限 使用docker命令时,每次都要sudo提权,否则就会报错提示无权限。 1.查看docker用户组及成员 sudo cat /etc/group | grep docker2.添加docker用户组 sudo groupadd docker3.添加用户到docker组 sudo gpasswd -a ${USER} docker4.增…...

【ROS系统】Ubuntu22.04系统中安装ROS2系统_ubuntu 安装ros2_GoesM
【ROS系统】Ubuntu22.04系统中安装ROS2系统_ubuntu 安装ros2_GoesM Excerpt ROS仿真、专为自动驾驶研发提供的系统平台_ubuntu 安装ros2 参考博客:ROS 安装详细教程 —— Ubuntu22.0.4 LTS 安装 Part 0. 准备 首先,我们需要一个Ubuntu系统。 Part 1. …...

MySQL8.0.22安装过程记录(个人笔记)
1.点击下载MySQL 2.解压到本地磁盘(注意路径中不要有中文) 3.在解压目录创建my.ini文件 文件内容为 [mysql] # 设置mysql客户端默认字符集 default-character-setutf8[mysqld] # 设置端口 port 3306 # 设计mysql的安装路径 basedirE:\01.app\05.Tool…...

Python中pip和conda的爱恨情仇
在使用pip和conda时,是否也有过以下的疑惑??? 目前只总结了以下常见的几种混淆,如有学者还有其它疑惑,欢迎留言讨论,我会解答更新,帮助自己理清的同时,也帮助其他同样困…...

HTTPS协议原理
目录 前言 1.理解加密和解密 2.为什么要加密 3.常见的加密方式 3.1对称加密 3.2非对称加密 4.数据摘要和数据指纹 5. 数字签名 6.HTTPS的加密策略 6.1只使用对称加密 6.2使用非对称加密 6.2.1服务端使用非对称加密 6.2.2双方都使用非对称加密 6.3对称加密非对称加…...

C语言每日一练------Day(6)
本专栏为c语言练习专栏,适合刚刚学完c语言的初学者。本专栏每天会不定时更新,通过每天练习,进一步对c语言的重难点知识进行更深入的学习。 今日练习题关键字:整数转换 异或 💓博主csdn个人主页:小小unicorn…...

springboot中使用ElasticSearch
引入依赖 修改我们的pom.xml,加入spring-boot-starter-data-elasticsearch <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>编写配…...

十二、集合(2)
本章概要 添加元素组集合的打印列表 List 添加元素组 在 java.util 包中的 Arrays 和 Collections 类中都有很多实用的方法,可以在一个 Collection 中添加一组元素。 Arrays.asList() 方法接受一个数组或是逗号分隔的元素列表(使用可变参数ÿ…...

【网络设备】交换机的概念、工作原理、功能以及以太网帧格式
个人主页:insist--个人主页 本文专栏:网络基础——带你走进网络世界 本专栏会持续更新网络基础知识,希望大家多多支持,让我们一起探索这个神奇而广阔的网络世界。 目录 一、认识交换机 二、交换机的主要功能 1、数…...

研磨设计模式day11观察者模式
目录 场景 代码示例 定义 观察者模式的优缺点 本质 何时选用 简单变型-区别对待观察者 场景 我是一家报社,每当我发布一个新的报纸时,所有订阅我家报社的读者都可以接收到 代码示例 报纸对象 package day11观察者模式;import java.util.Observ…...

第八周第二天学习总结 | MySQL入门及练习学习第四天
实操练习: 1.建立一个员工表和与之对应的部门表 2.建立外键约束 3.使用多表查询,直接查询部门表和员工表 发现:有很多多余的因笛卡尔乘积而带来的多余输出内容 我想要的到简单明了的数据结果,要消除多于因笛卡尔乘积带来的输出…...

WPF数据转换
在基本绑定中,信息从源到目标的传递过程中没有任何变化。这看起来是符合逻辑的,但我们并不总是希望出现这种行为。通常,数据源使用的是低级表达方式,我们可能不希望直接在用户界面使用这种低级表达方式。WPF提供了两个工具&#x…...

《Go 语言第一课》课程学习笔记(十三)
方法 认识 Go 方法 Go 语言从设计伊始,就不支持经典的面向对象语法元素,比如类、对象、继承,等等,但 Go 语言仍保留了名为“方法(method)”的语法元素。当然,Go 语言中的方法和面向对象中的方…...

基于RUM高效治理网站用户体验入门-价值篇
用户体验 用户体验基本包含访问网站的性能、可用性和正确性。通俗的讲,就是一把通过用户访问测量【设计者】意图的尺子。 本文目的 网站如何传递出设计者的意图,可能页面加载时间太长、或者页面在用户的浏览器中渲染时间太慢,或者第三方设备…...