C++ 简单学习

news2024/11/24 10:38:52

 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 ,0
          a = 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.coloradmin.cn/o/1987058.html

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

相关文章

学习vue3 三,组件基础,父子组件传值

组件基础 每一个.vue 文件都可以充当组件来使用 每一个组件都可以复用 父组件引入之后可以直接当标签使用 案例&#xff1a; App.vue <script setup lang"ts"> import BaseRefAndReactive from "./components/BaseRefAndReactive.vue";</sc…

Docker部署Node+Koa+TS+Mongo项目

Docker 简介 简而言之&#xff0c;Docker 容器轻量级、启动快、可移植&#xff0c;适合微服务架构。主要组件包括 Docker Engine、Docker 镜像、Docker 容器和 Docker Hub&#xff0c;它通过容器打包应用程序及其依赖项&#xff0c;使得应用在任何环境中都能一致运行。 这里不…

Selenium中send_keys上传图片方法以及可能失败的原因

Python Selenium是一个用于自动化浏览器操作的工具&#xff0c;可以用于模拟用户在浏览器中的各种操作。在使用Python Selenium进行自动化测试时&#xff0c;有时需要上传图片。下面是在这种情况下如何上传图片的步骤&#xff1a; 今天是主要说的是input标签&#xff0c;这种可…

基于R语言绘制GGE双标图3

参考资料&#xff1a; https://cran.r-project.org/web/packages/GGEBiplots/GGEBiplots.pdf GGE叠图法一分析品种环境互作模式的理想方法【作物学报】 GGE 双标图如何看&#xff1f;-CSDN博客 1、品种间两两比较 GGE 双标图可用于直接比较两个品种在各个试验点的表现&…

白银市场暴跌的技术分析与投资策略

一、白银市场暴跌与技术分析 周一&#xff08;8月5日&#xff09;&#xff0c;现货白银暴跌逾4.5%&#xff0c;并跌破关键的100日移动均线。FXStreet分析师Christian Borjon Valencia对银价技术走势进行了分析&#xff0c;指出银价前景转为看跌&#xff0c;技术面显示白银将进一…

探索Python并发的秘境:Greenlet库的奇幻之旅

文章目录 探索Python并发的秘境&#xff1a;Greenlet库的奇幻之旅背景&#xff1a;为何选择Greenlet&#xff1f;绿野仙踪&#xff1a;Greenlet是什么&#xff1f;安装&#xff1a;如何将Greenlet纳入囊中&#xff1f;功能探索&#xff1a;Greenlet的五大法宝场景应用&#xff…

【系统分析师】-综合知识-软件工程与项目管理

1、按照成本性态分类&#xff0c;可以分为固定成本、变动成本和混合成本。 &#xff08;1&#xff09;固定成本。管理人员的工资、办公费、固定资产折旧费、员工培训费、广告费、员工培训费、技术开发经费、办公场地及机器设备的折旧费、房屋及设备租金、管理人员的工资等。 …

提示工程:CO-STAR框架

在人工智能领域&#xff0c;尤其是大型语言模型&#xff08;LLM&#xff09;的应用中&#xff0c;提示工程已成为一项至关重要的技能。它不仅需要对技术有深刻的理解&#xff0c;还需要创造力和战略思维的结合。本文将探讨提示工程的重要性&#xff0c;详细介绍CO-STAR框架的使…

0209-开发状态切换(场景切换)功能

一、设置场景状态 1、已有方法 2、实现步骤 引用API&#xff1a;using UnityEngine.SceneManagement 写设置场景状态的方法 场景名字切换&#xff0c;需要获取mSceneName&#xff0c;他是私有的&#xff0c;给一个getset 3、问题 &#xff08;1&#xff09;同步加载 加载场…

【Web开发手礼】探索Web开发的秘密(十六)-Vue2(2)前端工程化、Element组件表格、分页

主要介绍了前端工程化Vue的开发流程、Element组件介绍以及常见的Element组件表格、分页&#xff01;&#xff01;&#xff01; 目录 前言 前端工程化 Vue项目-创建 Vue项目-目录结构 Vue项目-启动 Vue项目-配置端口 Vue项目开发流程 Element组件 快速入门 常见组件 表格…

2024杭电多校(4) 1008. 树形DNA【01Trie、哈希】

题意 给定两颗二叉树 S S S 和 T T T&#xff0c;如果对于 S S S 的某个子树 S ′ S^\prime S′&#xff0c;删除若干个&#xff08;或不删除&#xff09;其子树后&#xff0c;可以和 T T T 相同&#xff08;左子树与左子树匹配&#xff0c;右子树与右子树匹配&#xff0…

C++入门基础知识

在之前我们学习了C语言和初阶数据结构的相关知识&#xff0c;现在已经有了一定的代码能力和对数据结构也有了基础的认识&#xff0c;接下来我们将进入到新的专题当中&#xff0c;这个专题就是C。在C中我们需要花费更大的精力和更长的时间去学习这门建立在C语言基础之上的计算机…

新一代AI软件基础设施 | ZStack AIOS平台“智塔”发布

新一代 IT 基础设施&#xff0c;将从通用算力云平台转型为AI算力AIOS平台。 AI正在重构世界。正如世界是立体的&#xff0c;AI重构也正从多维度开启&#xff1a;基础设施重构&#xff0c;业务应用重构&#xff0c;交互模式重构&#xff0c;数据价值重构&#xff0c;生态系统重…

移动IP:让你的设备随时随地保持连接

随着无线网络技术的迅猛发展&#xff0c;在移动中进行数据通信已成为可能。成千上万的人正在使用移动设备畅享互联网&#xff0c;无论是在火车上、汽车内&#xff0c;还是在其他移动场景中。本文将带你了解移动IP&#xff08;Mobile IP&#xff09;的工作原理及其对网络应用的影…

LLM在线理解;神将网络理解;transform架构

目录 LLM在线理解 神将网络理解 transform架构 模型的子结构: 三个计算 计算1 计算2 计算3 LLM在线理解 LLM Visualization 神将网络理解 transform架构 模型的子结构: 词向量(Embedding) 前馈神经网络(Feed Forward) 残差连接(Add)和层标准化(Norm) 线性层(Linear…

Python版本和cuda版本不匹配解决办法

一、检查版本是否匹配 使用Python进入控制台&#xff0c;然后执行&#xff1a; >>>print(torch.cuda.is_available())如果输出为 False&#xff0c;则说明不匹配 退出Python环境&#xff0c;再检查系统版本&#xff1a; exit()nvcc -V 二、安装 去官网 PyTorch …

转载一篇关于对Linux磁盘部分mount和挂载的解释

转载自: http://t.csdnimg.cn/V3lgahttp://t.csdnimg.cn/V3lga

3_stm32_pwm呼吸灯

到目前已经可以进行基础的Led亮灭控制、使用定时器中断控制Led的亮灭。但是发现Led只有“亮”和 “灭”两种状态&#xff0c;那是否可以有更多状态&#xff1f;如何有更多状态呢&#xff1f;更进一步的想法&#xff0c;Led亮是有了电压差&#xff0c;其中一端是地&#xff0c;那…

C#:具体类=>抽象类=>接口的变化过程详解

文章目录 简单复习继承与多态具体类抽象类及成员使用语法 接口抽象类到接口的进化 简单复习继承与多态 下面,我用一个交通工具的例子来快速复习一下. 1.首先我定义一个基类Vehicle,代表交通工具的总称.里面定义了一个可被重写的成员方法Run. class Vehicle{public virtual voi…

Python Flask+Echarts实现葡萄酒质量的影响因素分析可视化

提示&#xff1a;本文章参考了哔哩哔哩的python课程李巍老师的 视频教程 文章目录 前言一、相关技术1.Flask2.Echarts3.词云 二、代码部分1.5个前端页面&#xff1a;2.代码 效果图 前言 数据分析是指用适当的统计分析方法对收集来的大量数据进行分析&#xff0c;将它们加以汇总…