C++ 简单学习

 C++简单编译

auto关键字 

auto 关键字用于自动类型推导。它允许编译器自动推断变量的类型,使得代码更加简洁和易于编写,尤其是在处理复杂类型或模板编程时。使用 auto 可以避免编写冗长的类型声明,同时减少由于类型不匹配导致的编译错误

auto x = 5; // x 的类型是 int  
auto y = 3.14; // y 的类型是 double  
auto z = 'a'; // z 的类型是 char  // 指针  
int* p = &x;  
auto p1 = &x; // p1 的类型是 int*  // 引用  
auto& r = x; // r 是 x 的引用,类型为 int&// 复杂的类型推导  
std::map<int, std::string> myMap = {{1, "one"}, {2, "two"}};  
auto iter = myMap.begin(); // iter 的类型是 std::map<int, std::string>::iterator

注意事项:

  • 初始化使用 auto 声明的变量必须被初始化,因为编译器需要依据初始化表达式来推导类型。

  • 指针和引用可以通过在 auto 后面添加 * 或 & 来声明指针或引用类型的变量。

  • 范围for循环auto 在范围for循环中非常有用,因为它可以自动处理迭代器的类型。
std::vector<int> v = {1, 2, 3, 4, 5};  
for (auto i : v) {  // i 的类型是 int,并且是 v 中元素的拷贝  
}  for (auto& i : v) {  // i 是对 v 中元素的引用,可以修改 v 中的元素  
}
  • 模版编程:在模板编程中,auto 尤其有用,因为它可以帮助避免编写复杂的类型声明
using namespace std;
int add(int *a,int *b)
{++ *a;++ *b;return *a + *b;
}
int main()
{int i =10,j =9;cout << add(&i,&j) <<endl;cout << i <<"," << j <<endl;
}

 

                                                                                                                             

 

引用 &

  1. 定义引用:
    int a = 10 ;
    int & b = a ; // b是a的引用

    ba指向内存中的同一个位置。对b的任何非const修改都会反映到a上。
  2. 引用的限制
    引用在定义时必须被初始化
    引用一旦被初始化,就不能再改变为引用另一个对象。
    引用不能为空

  3. 函数参数和返回值中的引用

    引用常用于函数参数和返回值中,以实现高效的数据传递和返回,
    ------ 函数参数:通过引用传递参数可以避免拷贝大型对象,提高程序效率。
     

    void swap(int& a, int& b) {  int temp = a;  a = b;  b = temp;  
    }

    ------ 函数返回值:通过引用返回可以避免拷贝,但需要注意避免返回局部变量的引用,因为这会导致悬垂引用
     

    int& findMax(int& a, int& b) {  return (a > b) ? a : b;  
    }
  4. 常量引用

    常量引用允许我们引用一个常量对象或非常量对象,但不允许我们通过这个引用来修改对象的值
     

    const int c = 30;  
    const int& d = c; // 正确:d是c的常量引用  
    int& e = c; // 错误:不能通过非常量引用来引用常量对象


简述指针与引用的关系?

 相同点:

  1. 间接访问两者都允许通过它们来访问和操作另一个变量的值,而不是直接访问该变量的内存地址。

  2. 函数参数在函数中,使用指针或引用作为参数可以避免复制大型对象,提高效率,并且允许函数修改传入的变量的值。

  3. 返回非局部变量的值都可以用来从函数中返回非局部变量的地址或引用,从而允许在函数外部访问和修改这些变量的值。

不同点:

(1)语法

  • 指针需要解引用(使用*操作符)来访问其指向的值。
  • 引用则像是一个变量的别名,不需要特殊的操作符来访问其值。

(2)空值

  • 指针可以被设置为nullptr(或NULL,在C++11之前),表示它不指向任何对象。
  • 引用必须在声明时被初始化,且一旦被绑定到一个对象,就不能再被改变为引用另一个对象,即引用不能为空。

(3) 赋值

  • 指针可以被重新赋值以指向另一个对象。
  • 引用一旦绑定到一个对象,就不能再指向另一个对象。

(3)类型安全

  • 指针可以进行算术运算(如递增或递减),这可能导致它指向无效的内存区域,降低类型安全性。
  • 引用不支持算术运算,这增加了类型安全性,但同时限制了灵活性。

(4)大小

  • 指针本身是一个变量,它存储的是另一个变量的内存地址,因此指针有大小(通常是机器字长)。
  • 引用则是一个别名,不占用额外的存储空间(不存储地址,只是别名),但从实现的角度来看,编译器可能会以指针的形式来处理引用。

(5)使用场景

  • 指针因其灵活性(如动态内存分配、数组操作、链表等数据结构)而被广泛使用。
  • 引用则因其安全性和简洁性(如函数参数传递、返回值等)而在C++中被推荐用于需要引用语义的场合。

 内联函数 inline

定义:

inline 是一种建议 不是命令,是否真的展开取决于编译器

声明:

内联函数的 inline 关键字只放在头文件不放在源文件中

虽然可以在函数声明前添加inline关键字,但这种方式通常是无效的,因为编译器在编译时只关注函数定义处的inline关键字。因此,通常将inline关键字与函数定义体放在一起

特点:

  • 编译时展开内联函数在编译时会被直接插入到调用该函数的地方,而不是像普通函数那样生成函数调用的指令。这消除了函数调用的开销,包括参数传递、栈帧创建和销毁等。
    #include <iostream> // 声明内联函数 
    inline int max(int a, int b) 
    {return (a > b) ? a : b; 
    }
    int main() 
    { 
    int x = 5, y = 10, z;
    z = max(x, y); // 这里调用max函数,编译器可能会将其内联展开 
    std::cout << "The maximum is " << z << std::endl;
    return 0; 
    }
  • 适用于简单函数:内联函数通常适用于函数体较小、执行时间较短的函数。如果函数体过大或包含复杂的控制结构(如循环、递归等),编译器可能不会将其内联,因为这可能导致代码膨胀和性能下降。
  • 代码膨胀:由于内联函数的代码会被复制到每一个调用处,因此如果内联函数被频繁调用或代码较大,可能会导致程序体积增大。
  • 通常放在头文件中:为了避免链接错误,内联函数的定义通常放在头文件中,以便在需要调用的地方进行内联展开。

 例如:

inline void fm(int &n)
{++n;
}
int main()
{int i =10;int j =20;fm(i);cout<< i <<endl;}
inline void fm(const int &n)
{n;
}
int main()
{int i =10;fm(10);cout<< i <<endl;}

 结果:11

            10

默认形参值

默认形参值只放在声明不放在定义

注意点:

  • 默认值的位置:一旦你为某个参数指定了默认值,那么该参数之后的所有参数都必须有默认值。

    int add ( int a = 0 , int b = 0 )
    {cout << "a = " << a <<endl;cout << "b = " << b <<endl;return a + b ;
    }int main()
    {cout << add() << endl;//可以传参一可以不传参,如果不传参则都为0//cout << add(10,20) << endl;return 0;
    }结果:a = 0 ,b = 0 ,0a = 10,b = 20 , 30

  • 函数声明与定义:通常,在函数声明中指定默认值,并在函数定义中省略这些值。但是,你也可以在函数定义中直接指定默认值,只要确保在调用函数之前,编译器已经看到了这些默认值(即,函数声明或定义在调用点之前)。

  • 头文件与源文件如果函数声明在头文件中,而定义在源文件中,那么默认值应该在头文件的函数声明中指定。

  • 重载与默认参数具有默认参数的函数可以被重载。编译器会根据提供的参数数量和类型来选择最合适的函数版本

  • 函数指针与默认参数:当通过函数指针调用函数时,默认参数不会生效。你需要显式地提供所有参数。

  • 构造函数与默认参数类的构造函数也可以有默认参数,这对于创建具有可选成员变量的对象非常有用。

函数重载

函数重载的基本规则

  • 函数名相同重载的函数必须具有相同的名称
  • 参数列表不同函数的参数列表必须不同。这可以是参数的类型不同、参数的个数不同,或者参数的顺序不同(尽管在实际应用中,改变参数顺序通常不是一个好的设计选择,因为它可能导致代码难以理解和维护)。
  • 返回类型可以相同也可以不同返回类型不是决定函数是否重载的因素。但是,习惯上,如果函数的功能相似,那么最好保持返回类型也一致,以增强代码的可读性。
  • 仅返回类型不同不足以构成重载如果两个函数只是返回类型不同,但参数列表完全相同,则编译器会报错,因为这不是有效的重载。
#include <iostream>  
using namespace std;  //函数重载示例 同名但不同参  
void print(int i) {  cout << "Printing int: " << i << endl;  
}  void print(double f) {  cout << "Printing float: " << f << endl;  
}  void print(const char* c) {  cout << "Printing character: " << c << endl;  
}  int main() {  print(7);          //调用 print(int)  print(7.7);        //调用 print(double)  print("Hello");    //调用 print(const char*)  return 0;  
}

 

const

const关键字是一个非常重要的特性,它用于指定变量的值在初始化之后不能被修改const可以应用于变量、指针、函数参数、返回值等多种情况,以提高代码的可读性和安全性

  1. 修饰变量
    const用于修饰变量时,表示该变量的值是一个常量,在程序运行过程中不能被修改
  2. 修饰指针
    (1)指向常量的指针(指针指向的值不能被修改)

    const int* ptr = &x;// ptr是一个指向整数的指针,但这个整数是const的,即*ptr的值不能被修改

    (2)常量指针(指针指向的值不能被修改,但指向的值可以改变)

    int* const ptr = &x; 
    // ptr是一个const指针,指向x,但ptr本身的值(即它所指向的地址)不能被修改

    (3)同时修饰指针和指向的值:

    const int* const ptr = &x; 
    // ptr是一个const指针,指向一个const整数,即ptr的值和*ptr的值都不能被修改
  3. 修饰函数参数
    在函数定义中,使用const修饰参数可以告诉调用者这个参数在函数内部不会被修改,这有助于编译器进行优化,并增加了代码的清晰度
     

    void display(const int& x) {  // 在这里,你不能修改x的值  cout << x << endl;  
    }
  4. 修饰返回值
    const也可以用于修饰函数的返回值,但这种情况比较少见。当const用于修饰返回值时,它表示返回的对象是一个常量,调用者不能通过这个返回值去修改对象的状态
     

    const int getValue() {  // 返回一个常量int  return 42;  
    }  // 注意,对于自定义类型(如类),返回const对象通常是为了表示这个对象是只读的,不应该被修改  
    const MyClass getMyClassInstance() {  // ...  
    }

    然而,对于自定义类型(如类)的返回值,如果返回的是对象本身而不是引用或指针,那么const修饰符可能并不那么有用,因为返回值是一个临时对象,它本身就不能被赋值给非const的变量(这会导致拷贝)。但如果是返回引用或指针,那么const修饰符就显得非常重要了

  5. 成员函数
    在类中,const成员函数表示该函数不会修改类的任何成员变量(除了mutable修饰的成员变量)。这有助于保证对象的状态在调用该函数后不会发生变化

    class MyClass {  
    public:  void myFunction() const {  // 这里不能修改类的成员变量  }  
    };

 不能实现

常引用 

void(const int &a) 

常引用通过在类型前添加const关键字来声明。常引用只能用于读取它所引用的数据,而不能用于修改。这使得常引用在以下场景中特别有用:

  1. 保护数据:当你想要通过函数参数传递一个对象,但又不希望这个函数修改这个对象时,可以使用常引用。
  2. 提高效率:对于大型对象或容器,通过引用传递可以避免不必要的复制,同时const修饰符又保证了数据的安全性。
  3. 函数返回值:返回对内部成员或局部静态变量的常引用可以避免拷贝,并保护这些变量不被外部修改。

非常引用(或者普通引用)

void (int &a)

没有const修饰的引用就是非常引用或普通引用。它允许通过引用修改它所引用的数据。非常引用在需要修改数据的函数中非常有用,因为它们提供了对原始数据的直接访问
 

#include <iostream>  
using namespace std;  void printValue(const int& x) 
{ 
// 使用常引用接收参数,保证不会修改x  cout << x << endl;  
}  void modifyValue(int& x) 
{
// 使用非常引用接收参数,可以修改x  x = 10;  
}  int main() {  int a = 5;  printValue(a); // 输出5  modifyValue(a); // 修改a的值为10  printValue(a); // 现在输出10  return 0;  
}

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

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

相关文章

论文阅读报告: 在时间双向图上查询基于时间的的密集子图 | ICDE 2024

摘要 本文提出了一个新的模型&#xff08;α, β, T&#xff09;-core&#xff0c;用于在时间双向图上寻找凝聚子图。时间双向图中&#xff0c;不同实体之间的关系随着时间的推移而变化。为了提高查询效率&#xff0c;本文提出了顶点分区和时间分区的历史索引&#xff08;VH-I…

Java学习Day24:基础篇14:多线程

1.程序、进程和线程 程序 进程 进程(process)是程序的一次执行过程&#xff0c;或是一个正在执行的程序。是一个动态的过程&#xff1a;有它自身的产 生、存在和消亡的过程。 如&#xff1a; 运行中的QQ运行中的音乐播放器视频播放器等&#xff1b;程序是静态的&#xff0c…

【大模型从入门到精通13】openAI API 构建和评估大型语言模型(LLM)应用1

这里写目录标题 构建和评估大型语言模型&#xff08;LLM&#xff09;应用开发性能评估指标从开发到部署高风险应用LLM应用开发的最佳实践和建议从小处着手快速迭代自动化测试根据应用需求定制评估考虑伦理影响 构建和评估大型语言模型&#xff08;LLM&#xff09;应用 开发和部…

Sqli-labs-master靶场--布尔盲注

目录 1、布尔盲注 2、布尔盲注的流程&#xff08;以靶场less-8为例&#xff09; 2.1输入id尝试是否存在注入点 2.1.1通过以上尝试&#xff0c;联想到可能是布尔盲注 2.2猜测数据库长度 2.3获取数据库名 2.3.1python脚本获取 代码&#xff1a; 获取结果为&#xff1a; …

Hive SQL ——窗口函数源码阅读

前言 使用Starrocks引擎中的窗口函数 row_number() over( )对10亿的数据集进行去重操作&#xff0c;BE内存溢出问题频发&#xff08;忘记当时指定的BE内存上限是多少了.....&#xff09;&#xff0c;此时才意识到&#xff0c;开窗操作&#xff0c;如果使用 不当&#xff0c;反而…

1. js混淆-源码乱码

目录 调试干扰参数逆向 调试干扰 打开开发者工具&#xff0c;首先会进入 setInterval 生成的 debugger 将 uzt.js uyt.js 内容替换 将这两个文件的内容置空&#xff0c;并刷新页面就可以正常调试了 参数逆向 点击翻页&#xff0c;可以发现 https://match.yuanrenxue.cn/api…

Arduino导入实例程序的过程,实例包文件却编译显示缺失文件

参考中实例程序中的readme.txt 导入方式 下面是文档中的使用方式 1.基本信息&#xff1a; 本例程是基于Arduino进行开发的&#xff0c;例程均在E-Paper ESP8266 Driver Board上进行了验证;2.基本使用&#xff1a;方法1&#xff1a;将整个esp8266-waveshare-epd文件夹复制到C…

【Go】通过反射解析对象tag信息,实现简易ORM

反射是运行时&#xff0c;需要在运行时解析类型信息&#xff0c;编译期无法优化这些操作&#xff0c;因此比编译时已知类型信息的直接调用效率要低。 package mainimport ("fmt""reflect""strings" )type Person struct {Name string json:&quo…

PicGo + gitee 免费搭建个人图床

目录 1 图床概念2 使用gitee和PicGo搭建图床流程2.1 下载安装PicGo工具 3 图片上传错误处理3.1 PicGo客户端提示404错误信息图片上传失败3.2 PicGo客户端提示400错误信息图片上传失败 1 图床概念 ​ "图床"是一个网络术语&#xff0c;它指的是一种用于存储和托管图片…

理解张量拼接(torch.cat)

拼接 维度顺序&#xff1a;对于 3D 张量&#xff0c;通常可以理解为 (深度, 行, 列) 或 (批次, 行, 列)。 选择一个dim进行拼接的时候其他两个维度大小要相等 对于三维张量&#xff0c;理解 torch.cat 的 dim 参数确实变得更加抽象&#xff0c;但原理是相同的。让我们通过一…

算法力扣刷题记录 六十九【动态规划基础及509. 斐波那契数】

前言 调整一下做题顺序&#xff0c;多个章节同步进行&#xff0c;穿插练习。可以在各章节的专栏中找同一类。 记录 六十九【动态规划基础】。 一、动态规划理论基础学习 参考学习链接 二、509. 斐波那契数 2.1 题目阅读 斐波那契数 &#xff08;通常用 F(n) 表示&#x…

html+css+js网页设计 中国移动5个页面(带js)

htmlcssjs网页设计 中国移动5个页面&#xff08;带js&#xff09; 网页作品代码简单&#xff0c;可使用任意HTML编辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xf…

Cpp中的this指针--复习记录

1.什么是this指针? 每个类都有一个this指针&#xff0c;我们的非静态成员函数可以通过这个this指针来操作对象的成员属性。this指针存储的就是类的实例的地址&#xff0c;this指针时时刻刻指向的都是这个实例对象本身。 由下图可知: 我在主函数中栈上创建了一个类的实例(由操…

【Python-实操】LabelMe to YOLOv8 Converter

LabelMe to YOLOv8 Converter 这是一个 Python 脚本&#xff0c;用于将 LabelMe 标注工具导出的 JSON 文件转换为 YOLOv8 格式的标注文件&#xff0c;并同时在图像上绘制标注的多边形。 功能 读取 LabelMe JSON 文件。解码并显示图像。从 classes.txt 文件加载类别标签。将多…

Java | Leetcode Java题解之第327题区间和的个数

题目&#xff1a; 题解&#xff1a; class Solution {public int countRangeSum(int[] nums, int lower, int upper) {long sum 0;long[] preSum new long[nums.length 1];for (int i 0; i < nums.length; i) {sum nums[i];preSum[i 1] sum;}BalancedTree treap ne…

Java参数传递

Java参数传递 一、 方法重载 一个类中可以存在多个同名的方法&#xff0c;只要这些方法的参数列表不同即可。 参数列表不同&#xff1a;参数个数或者参数类型不同方法重载与修饰符、返回值类型等统统无关&#xff0c;只看参数列表 二、 可变个数的形参 从Java5.0开始&…

陶瓷材质的防静电架空地板越来越受欢迎的原因

目前市面上的陶瓷防静电架空地板主要分为两种&#xff1a;钢基和硫酸钙基。前者是以全钢冲孔裸板作为板基&#xff0c;经粘接、固定整型和灌浆的方式加工而成&#xff0c;后者是以复合硫酸钙板为基材&#xff0c;表面粘接防静电陶瓷砖&#xff0c;四周导电PVC边条封边。近年来陶…

【C++】vector 的模拟实现

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…

02_快速启动 Demo 创建 Electron 项目、electron-forge 搭建一个 electron 项目、手动创建electron项目

快速启动 Demo 创建 Electron 项目 一、克隆一个仓库、快速启动一个项目二、electron-forge 搭建一个 electron 项目三、手动搭建一个 electron 项目四、开发工具中配置 Eslint 一、克隆一个仓库、快速启动一个项目 要使用 git 的话首先电脑上面需要安装 git //克隆示例项目的…

Qt3D给圆环等立体图形添加纹理图片

添加纹理图片&#xff0c;首先需要自己找一个纹理图&#xff0c;当然了&#xff0c;随便什么图片都行。 创建3D图形的主要步骤查看另一篇文章。 这里主要代码如下&#xff1a; 使用QTextureLoader加载图片&#xff0c;图片路径需为qrc:/的路径。 auto *planeTransform1 ne…