C++入门(嵌入式学习)

news/2024/9/23 4:23:50/

C++入门学习

  • 前言
    • C++概述
    • C和C++的区别
  • 引用
    • 引用概念
    • 引用性质
    • 引用的应用
  • C++输入和赋值
  • string字符串
  • 函数提高
    • 函数的默认值
    • 默认值的注意事项
    • 函数的重载
    • 函数重载可能产生的问题
      • 扩充
    • 内联函数

前言

C++概述

C++是一种通用的高级编程语言,它是由Bjarne Stroustrup于20世纪80年代初在C语言的基础上发展而来的。C++扩展了C语言的功能,引入了面向对象编程(OOP)和泛型编程的概念,使得程序员能够以更高级别的抽象来构建复杂的应用程序。

C++具有以下特点:

面向对象编程(OOP)
C++支持面向对象编程范式,提供了类、对象、继承、多态等概念。面向对象编程使得程序更易于组织、维护和扩展,通过封装、继承和多态性,可以实现代码重用和模块化开发。

泛型编程
C++引入了模板(templates)机制,允许编写通用的代码,以便处理不同类型的数据。模板使得数据类型和算法可以更加灵活地组合,从而提高代码的复用性和效率。

高效性
C++允许直接访问底层的硬件资源,并提供了对内存和指针的直接操作。这使得C++在开发需要高性能和低级别控制的应用程序时非常有用,例如游戏引擎、嵌入式系统和图形处理。

标准库
C++标准库提供了广泛的功能和数据结构,包括输入/输出、字符串处理、容器、算法、多线程支持等。标准库是C++程序开发中不可或缺的部分,它提供了许多常用的工具和功能,可以大大提高开发效率。

兼容性
C++是C语言的超集,几乎所有的C语言代码都可以在C++中进行编译和运行。C++编译器可以直接使用C语言的函数和库,这使得现有的C代码可以无缝地集成到C++项目中。

可移植性
C++的标准化使得它在不同的平台和操作系统上具有很好的可移植性。开发人员可以编写一次代码,然后在多个平台上进行编译和运行,大大减少了开发和维护的工作量。

C++是一种功能强大且灵活的编程语言,它在许多领域都得到了广泛应用,包括系统开发、游戏开发、嵌入式系统、科学计算、图形处理和大数据分析等。它也是许多重要的开源项目和库的首选语言,如Qt、Boost和OpenCV等。

C和C++的区别

C和C++是两种编程语言,它们有许多相似之处,但也有一些重要的区别。下面是C和C++之间的主要区别:
面向对象编程
C++是一种支持面向对象编程(OOP)的语言,而C语言是过程式编程语言。面向对象编程允许使用类、对象、继承、多态等概念,这使得C++在处理复杂的程序结构时更加方便和灵活。

编程范式
C是一种过程式编程语言,而C++是一种多范式编程语言,支持面向过程编程、面向对象编程和泛型编程。C++在C的基础上添加了类和对象的概念,使得面向对象编程更加容易。

类和对象
C++引入了类和对象的概念,这是面向对象编程的核心。类是一种自定义的数据类型,可以包含数据成员和成员函数。对象是类的实例,可以通过创建对象来使用类的功能。C没有类和对象的概念,它更加关注函数和过程的编写。

继承和多态
C++支持继承和多态,这些是面向对象编程的重要特性。继承允许一个类继承另一个类的属性和方法,而多态允许使用基类的指针或引用来调用派生类的方法。C不支持这些特性。

异常处理
C++支持异常处理机制,可以用于处理程序运行中的异常情况,如内存分配失败、文件读写错误等。C语言没有内置的异常处理机制,通常使用错误码来处理错误。

兼容性
C++是C的超集,这意味着符合C语法规范的代码也可以作为C++代码进行编译。C++可以调用C语言编写的函数,并且大部分C语言代码可以直接用于C++。但是,C++中引入的一些新特性在C中不可用,因此使用这些特性的代码不能直接用于C。

扩展性
C++比C语言具有更丰富的功能和库,它引入了许多新的特性,例如类和对象、模板、异常处理、命名空间等。这使得C++在开发大型项目时更具扩展性,能够更好地组织和管理代码。

标准库
C++标准库提供了许多C语言标准库的扩展和增强版本,包括对输入/输出、字符串处理、容器、算法、文件操作等的支持。C++标准库还引入了一些新的特性,例如STL(标准模板库),它提供了强大的数据结构和算法。

内存管理
C++相对于C语言提供了更高级的内存管理机制。C++引入了构造函数和析构函数,用于对象的创建和销毁,这使得内存管理更加方便和安全。此外,C++还引入了运算符重载和引用,允许更灵活地操作内存。

这些是C和C++之间的一些主要区别。选择使用哪种语言取决于项目的需求、团队的技能和个人的偏好。如果只需要进行简单的过程式编程,C可能是一个更好的选择。如果需要更多的面向对象编程特性和更丰富的库支持,C++可能更适合。

引用

引用概念

在C++中,引用是一种为对象起别名的机制。引用提供了对对象的间接访问,使得可以通过使用引用来操作原始对象,而无需直接操作指针或拷贝对象。引用在语法上类似于指针,但有一些重要的区别。

以下是关于引用的一些重要概念:

  1. 引用声明:引用必须在声明时进行初始化,并且一旦初始化后,它将一直引用同一个对象。引用的声明方式是使用&符号,将引用类型放在原对象类型之前。例如,int& ref = x;ref声明为一个整型引用,并将其初始化为变量x
  2. 别名:引用为对象提供了一个别名,可以通过引用使用对象的名称。例如,int x = 5; int& ref = x;,通过ref可以操作变量x
  3. 与指针的区别:引用与指针不同。指针是一个独立的对象,可以指向不同的对象或者为nullptr,而引用始终引用同一个对象,并且无法更改其指向其他对象。此外,引用不需要使用解引用运算符(*)来访问对象,因为引用本身就是对对象的直接引用。
  4. 函数中的引用参数:在函数中使用引用作为参数,可以实现对实参的直接修改,而不是对副本的操作。这可以避免在函数调用时发生对象的拷贝,提高性能和效率。函数中使用引用参数的方式是在参数类型前面加上&符号。例如,void increment(int& x) { x++; },这个函数会直接修改传入的变量的值。
  5. 引用作为返回值:函数也可以返回引用作为结果,这样可以返回对函数内部对象的引用,从而允许在调用端继续对该对象进行操作。但是需要注意避免返回对局部对象的引用,因为局部对象在函数执行完毕后会被销毁。
    引用在C++中具有许多用途,例如在函数参数传递中避免对象拷贝、实现运算符重载、实现容器类等。引用可以使代码更加简洁、高效和易读。但同时需要小心引用的使用,确保引用始终引用有效的对象,避免出现悬空引用或引用未初始化的对象。

引用可以作为一个变量或者对象的别名。操作引用就相当于操作变量
引用的类型和变量类型保持一致

例:

#include <iostream>
using namespace std;
int main()
{int a=10;int & b=a;cout<<a<<" "<<b<<endl; //10 10cout<<&a<<" "<<&b<<endl; //0x61fe88 0x61fe88b++;cout<<a<<" "<<b<<endl; //11 11
}

引用性质

性质一
成为一个变量的引用之后,就不能成为其他变量的引用。
了解内容:指针的本质 是指针常量
int & b=a; //相当于int * const b=&a;
例:

#include <iostream>
using namespace std;
int main()
{int a=10;int & b=a; //b是a的引用cout<<&a<<" "<<&b<<endl; //0x61fe78 0x61fe78int c=20;b=c; //这里只是把c的值给了bcout<<a<<" "<<b<<" "<<c<<endl; //20 20 20cout<<&b<<" "<<&c<<endl; //0x61fe78 0x61fe74//&b=c; 错误 不能成为其他变量的引用
}

性质二
引用必须初始化,并且不能为NULL

#include <iostream>
using namespace std;
int main()
{//int & c; 错误 引用必须初始化//int & c=NULL;  错误 引用不能为NULL
}

性质三
当作为纯数字的引用时,这时需要加const修饰,代表引用指向的内容不可更改

#include <iostream>
using namespace std;
int main()
{//int & a=100; //引用的权限时可读 可写   数字100是纯数值 可读const int &a=100; cout<<a<<endl;
}

性质四
const引用不可以直接更改变量的值。变量本身是可以更改数值,变量更改数值之后,引用的值也会跟着一起更改

#include <iostream>
using namespace std;
int main()
{int a=30;const int & b=a;//b++; const修饰的引用不可更改其值a++;cout<<a<<" "<<b<<endl; //31 31
}

引用的应用

c++函数的参数有两种形式的传递:
1.值传递
2.引用传递
两种传递方式的区别:
引用传递:可以直接操控变量,并且不会产生副本。
值传递:会产生副本(临时变量),不可以直接操控改变变量本身。
引用的方式要比指针更简洁,方便。

#include <iostream>
using namespace std;
void swap1(int a,int b){int t=a;a=b;b=t;
}
void swap2(int * a,int *b){int t=*a;*a=*b;*b=t;
}
void swap3(int & a,int &b){int t=a;a=b;b=t;
}
int main()
{int a=10,b=20;swap1(a,b);cout<<a<<" "<<b<<endl;swap2(&a,&b);cout<<a<<" "<<b<<endl; //20 10swap3(a,b);cout<<a<<" "<<b<<endl; //10 20
}

引用做参数好处:
不会为参数创建临时的内存空间,也就不需为其传值,提高了参数传递的效率。

C++输入和赋值

输入输出

#include <iostream>
using namespace std;
int main()
{int a,b;
//输入的第一种方式
//  cin>>a;
//  cin>>b;//输入的第一种方式cin>>a>>b;cout<<"输出数值:"<<a<<" "<<b<<endl;
}

c++赋值方式

#include <iostream>
using namespace std;int main()
{int a;a=10;int c(20); //把20的值赋给cint b(c); //把c的值赋值给bcout<<a<<" "<<c<<endl; //10 20cout<<b<<endl; //20double d=3.14;int e(d);cout<<e<<endl;//3
}

string字符串

c++中使用string类型来存储字符串,string字符串是c++中内置的一个类。里面有很多处理字符串的方法。可以替代c语言中的字符数组

#include <iostream>
using namespace std;
int main()
{string str="hello";//cin>>str;cout<<str<<endl;cout<<str.size()<<endl; //得到字符串长度for(int i=0;i<str.size();i++){cout<<str[i]<<" ";}
}

c++11中支持for each的方式遍历字符串,需要.pro配置文件中加上c++11的支持

QMAKE_CXXFLAGS += -std=c++11
在这里插入图片描述

 //for each 在c++11版本中可以使用for(char ch:str){ //从str中依次取 每个都是char类型 cout<<ch<<" ";}cout<<endl;cout<<str[5]<<endl; //这时不会报错//cout<<str.at(5)<<endl; //会报std::out_of_range 超出范围错误

函数提高

函数的默认值

c++中之前函数参数有默认值。如果调用时不给默认值赋值,就使用默认值。否则就用传入的值替代默认值。

#include <iostream>
using namespace std;
void show(int a,int b=20)
{cout<<a+b<<endl;
}
int main()
{show(10); //b使用默认的20show(10,30); //b使用传入的30
}

练习:画图软件默认颜色是黑色

#include <iostream>
using namespace std;
void draw(string color="黑色"){cout<<"画笔颜色是"<<color<<endl;
}
int main()
{draw();draw("red");
}

默认值的注意事项

1.当有多个参数时,其中一个有默认值,其后的参数都需要有默认值。称为“向后原则“

#include <iostream>
using namespace std;
//method2是错误的
//void method2(int a,int b=10,int c) 
//{
//    cout<<a<<" "<<b<<" "<<c;
//}
void method(int a,int b=10,int c=20)
{cout<<a<<" "<<b<<" "<<c;
}
int main()
{method(1,2);
}

2.当函数的声明和定义分离的时候,这时默认值只需要加在其中一个地方,通常是加在声明处

#include <iostream>
using namespace std;
void method(int a,int b,int c); //声明没有默认值
void method(int a,int b=20,int c=30) //定义给出默认值
{cout<<a<<" "<<b<<" "<<c<<endl;
}
void method2(int a,int b=1,int c=2);//method2声明处给出默认值cout<<a<<" "<<b<<" "<<c<<endl;
}
int main()
{method(1,2);method2(0);
}

函数的重载

函数重载是C++中的一种特性,允许在同一作用域内定义多个同名但参数列表不同的函数。通过函数重载,可以根据不同的参数类型和个数来调用适合的函数。

函数重载的特点如下:

1.函数名称相同:在函数重载中,多个函数具有相同的名称,这使得代码更加简洁和易读。
2.参数列表不同:函数重载要求函数的参数列表必须不同,可以通过参数的类型、顺序和个数来区分不同的函数。
3.返回值类型不同:函数重载允许函数的返回值类型相同或不同。重载函数的返回值类型通常不是决定函数重载的条件,因为4.编译器可以通过参数列表来区分函数。
5.函数体可以相同或不同:重载函数的函数体可以相同或不同,具体取决于函数的实现需求。

函数重载的优势在于提供了灵活性和代码复用性,可以根据不同的需求选择合适的函数进行调用。通过函数重载,可以为相似但参数不同的操作提供一致的接口。

以下是一个函数重载的示例:

// 函数重载示例
int add(int a, int b) {return a + b;
}double add(double a, double b) {return a + b;
}int main() {int result1 = add(2, 3);           // 调用int版本的add函数double result2 = add(2.5, 3.7);    // 调用double版本的add函数return 0;
}

在上述示例中,add 函数被重载了两次,一次接受两个整数参数,另一次接受两个双精度浮点数参数。根据传入的参数类型,编译器可以决定调用适合的函数。

需要注意的是,函数重载的条件是函数的参数列表不同,但返回值类型不是决定函数重载的条件。如果只有返回值类型不同而参数列表相同的函数,是不允许重载的。

函数重载的注意事项:
1.避免过度使用函数重载,以免导致代码可读性下降。
2.函数重载应该有明确的语义区分,避免造成调用的歧义。
3.函数重载时应考虑隐式类型转换的影响,避免导致意外的函数调用。

总结起来,函数重载是C++中一种便捷而灵活的特性,通过在同一作用域内定义具有相同名称但不同参数列表的函数,可以提高代码的可读性和代码复用性。

#include <iostream>
using namespace std;
void show(int a){cout<<"show(int a)"<<endl;
}
void show(int a,int b){ //通过参数个数不同区分cout<<"show(int a,int b)"<<endl;
}
void show(int a,double b){ //参数的类型来区分cout<<"show(int a,double b)"<<endl;
}
void show(double a,int b){ cout<<"show(double a,int b)"<<endl;
}
//void show(int b,int a){ //错误
//    cout<<"show(int b,int a)"<<endl;
//}
int main()
{show(2,3.5); //show(int a,double b)show(2.5,3); //show(double a,int b)
}

练习:
getMeassage()函数做重载
第一个输出name 第二个输出name 和 age,第三个输出name ,age,sex

#include <iostream>
#include<string>
using namespace std;void getMesage(string name)
{cout<<name<<endl;
}
void getMesage(string name,int age)
{cout<<name<<" "<<age<<endl;
}
void getMesage(string name,int age ,string sex)
{cout<<name<<" "<<age<<" "<<sex<<endl;
}
int main()
{getMesage("张三");getMesage("张三",33);getMesage("张三",33,"man");
}

函数重载可能产生的问题

1.函数返回值不同不能区分函数重载
2.函数重载和函数默认值是不能一起使用,会产生问题
例:

#include <iostream>
#include<string>
using namespace std;void getMesage(string name)
{cout<<name<<endl;
}
//string getMesage(string name) //通过返回值不同不能区分函数重载
//{
//    return name;
//}
void getMesage(string name,int age)
{cout<<name<<" "<<age<<endl;
}void getMesage(string name,int age ,string sex="女") //函数重载和默认值不可以连用
{cout<<name<<" "<<age<<" "<<sex<<endl;
}
int main()
{getMesage("张三");getMesage("张三",33);getMesage("张三",33,"man");
}

扩充

函数重载是C++中的一种特性,允许在同一作用域内定义具有相同名称但参数列表不同的多个函数。尽管函数重载提供了便利和灵活性,但在使用过程中也可能引发一些问题。以下是一些可能的问题:

1.模糊性
当函数重载存在时,编译器需要根据调用上下文选择最匹配的函数。如果存在多个函数都可以匹配,编译器可能无法确定最佳匹配,导致编译错误。这种模糊性可能会给开发人员带来困惑,需要仔细设计和处理函数重载。

2.意外调用
函数重载的存在可能导致在调用时意外选择了错误的函数。如果函数签名非常相似,调用者可能会错误地选择了与其意图不符的函数,这可能导致程序出现错误或产生不正确的结果。

3.隐藏功能
函数重载可能导致某些函数被其他函数隐藏。如果函数名称相同但参数列表不同的函数定义了多个,某些函数可能会被隐藏,使其无法通过函数名直接访问。这可能会导致代码可读性降低,因为需要更多的上下文信息才能确定到底调用了哪个函数。

4.过度使用
函数重载容易被滥用,导致代码中存在过多的重载函数。如果过载函数过于频繁,代码可读性和维护性可能会降低,因为开发人员需要花更多的时间和精力来理解和管理所有的重载情况。

为了避免上述问题,以下是一些建议:
1.尽量避免函数重载过于相似的函数签名,以减少调用模糊性和意外调用的可能性。
2.明确规定函数重载的行为,确保调用者能够正确地选择目标函数。这可以通过良好的文档和注释来提供必要的信息。
3.使用有意义的函数名称,以便开发人员在调用时能够准确理解函数的功能和用途。
4.当函数重载过多或导致混淆时,可以考虑使用其他方法来实现相似的功能,例如使用不同的函数名称或使用参数默认值来替代函数重载。
总之,函数重载是C++中的强大特性,但需要谨慎使用。合理的设计和理解函数重载的行为将有助于减少潜在的问题并提高代码的可读性和可维护性。

内联函数

内联函数是C++中的一种函数声明方式,用于提高函数调用的效率。通常,函数调用涉及将控制权从当前位置转移到函数的代码块,然后再返回到调用点。而内联函数的特点是在调用处直接展开函数体,避免了函数调用的开销。

使用内联函数有以下几点注意事项
1.内联函数的声明通常放在头文件中,以便在需要调用该函数的源文件中进行内联展开。
2.使用关键字 inline 来声明内联函数。在函数定义或函数声明前加上 inline 关键字即可。
3.内联函数的定义应该放在头文件中或者在每个调用该函数的源文件中进行定义,以便编译器能够在编译时将函数体直接插入4.到调用处。
5.内联函数适用于函数体较小且频繁调用的情况。对于复杂的函数或递归函数,内联展开可能不会带来性能提升,并且会增加代码体积。
6.内联函数的展开由编译器决定,编译器可能会根据函数的复杂性、调用频率等因素来判断是否进行内联展开。

使用内联函数的优点
1.减少函数调用开销:内联函数避免了函数调用的开销,可以减少函数调用时的栈操作、参数传递等额外的开销。
2.提高执行速度:由于内联函数将函数体直接插入到调用处,避免了跳转和返回的开销,从而可以提高程序的执行速度。
3.优化循环代码:内联函数在循环中调用时特别有用,可以减少函数调用次数,提高循环的执行效率。
需要注意的是,内联函数的使用并不一定总能带来性能上的提升。编译器会根据内联函数的复杂性和调用情况进行决策,因此在使用内联函数时应该结合实际情况进行评估,并进行性能测试和分析。
总之,内联函数是一种优化函数调用开销的方式,在一些场景下可以提高程序的执行效率。但需要注意合理使用内联函数,并在必要时进行性能测试,以确保其真正带来性能上的改进。
内联函数在编译时,会将函数体的内容展开到调用处,节省了函数调用的时间。

内联函数使用条件
1.函数体内容简单(5行以下)
2. 函数运行时间极短
3. 调用的次数比较频繁

#include <iostream>
#include<string>
using namespace std;
inline void show(){ cout<<"hello"<<endl;
}
int main()
{show();
}

http://www.ppmy.cn/news/334446.html

相关文章

PostgreSQL 主从复制方案

PostgreSQL 主从复制方案是一种常见的数据库高可用性方案&#xff0c;它允许在主服务器上进行写入操作&#xff0c;而从服务器则复制主服务器上的数据&#xff0c;并可以承担读取操作的负载。 以下是一个基本的 PostgreSQL 主从复制方案&#xff1a; 配置主服务器&#xff1a;…

什么是AOC?

AOC&#xff08;即Active Optical Fiber有源光纤&#xff09;有源光缆&#xff0c;是指通信过程中需要光收发器件&#xff0c;将电信号转换成光信号&#xff0c;或将光信号转换成电信号的通信线缆&#xff0c;光缆两端的光收发器提供光电转换以及光传输功能。 AOC有源光缆是由多…

AOC的计算

AOC指的是PR(精度-召回)曲线的曲线下面积&#xff0c;用于评估目标检测网络的性能。 AOC的计算过程如下&#xff1a; 1、获得网络推断的pred_bbox、pred_class、pred_score和真值gt_bbox、gt_class 2、对于每个类别&#xff0c;根据iou条件&#xff0c;增加一个正例(TP)或负例(…

AOC的显示器真的很烂

也不知道能用其它的什么词来形容AOC的显示器了&#xff0c;自从上次返修后不过半年多时间&#xff0c;显示器又再度出现划痕&#xff01;也不知道是怎么出来的&#xff0c;似乎是有很多道划痕划在某个薄膜&#xff0c;但这层膜又不在外表。也罢&#xff0c;再坚持上半年&#x…

LC-显示器2297

题目描述 你的一个朋友刚买了一台新电脑。 到目前为止&#xff0c;他曾经使用过的最强大的计算机是袖珍计算器。 现在&#xff0c;看着他的新电脑&#xff0c;他有点失望&#xff0c;因为他非常喜欢他的计算器的LC显示器。 所以你决定编写一个程序&#xff0c;在他的计算机上以…

睡眠脑电中的神经跨频率耦合函数

导读 人类大脑是一个紧密连接的复杂系统。虽然其结构比较固定&#xff0c;但它可以实现很多不同的功能。其中一个重要的功能是自然睡眠过程&#xff0c;这个过程可以改变意识和随意肌肉活动。在神经层面上&#xff0c;这些改变会伴随着大脑连接的变化。为了揭示这种与睡眠相关…

AOC1952 显示屏 输入不支持

选择对应的模式即可修正错误提示

固态硬盘Ghost安装Windows 10无法引导的问题

机器配置如下: 电脑型号 技嘉 B360M POWER 台式电脑操作系统 Windows 10 64位 ( DirectX 12 )处理器 英特尔 Core i7-8700 @ 3.20GHz 六核主板 技嘉 B360M POWER ( 英特尔 PCI 标准主机 CPU 桥 - CannonLake - A308 )显卡 …