C++入坑基础知识点

news2024/11/20 14:32:26

当学习了C语言之后,很多的小伙伴都想进一步学习C++,但两者有相当一部分的内容都是重叠的,不知道该从哪些方面开始入门C++,这篇文章罗列了从C到C++必学的入门知识,学完就算是踏入C++的大门了。

1. 命名空间

写C的时候,偶尔可能不小心就和库函数冲突了,又或者当两个程序员以相同的名字命名变量或函数,就会发生冲突。C++就提出了一个很好的解决方案——命名空间

命名空间的关键字是namespace,定义方式如下:

【定义方式】

namespace N1
{
    int a = 3;
    int b = 4;
​
    int Add(int x1, int x2)
    {
        return x1 + x2;
    }
​
    struct Node
    {
        struct Node* next;
        int val;
    };
​
    namespace N2
    {
        int c = 0;
        int d = 0;
    }
}

从示例中可以看出,命名空间中可以包含变量、函数、类型以及嵌套另一个命名空间

【使用方式】

1. 命名空间+作用域限定符

int main() {
    printf("%d\n", N1::a);
    return 0; 
}

2. using将命名空间中某个成员引入

using N1::b;
int main() {
    printf("%d\n", N1::a);
    printf("%d\n", b);
    return 0; 
}

3. using namespace 变量空间

using namespace N1;
int main() {
    printf("%d\n", a);
    printf("%d\n", b);
    return 0; 
}

2. 输入输出

其实C语言的printf/scanf在C++中还可以使用,不过C++有独有的输入输出方式,就是cin/cout

【使用说明】

1. 必须包含iostream头文件,注意是<iostream>

2. 需要使用命名空间std,因为cin/cout在其中的(日常练习可以这么做,但做项目的时候最好使用 std::cin 的方式展开)

3. 使用时要用<<流插入操作符/>>流提取操作符,不知道是什么没关系,看示例是怎么用的就行,cout用<<,cin用>>  

4. 变量之间也是用<<或>>连接,如果需要换行用endl

【示例】

#include <iostream>
using namespace std;
​
int main()
{
    cout << "hello world!" << endl;
    return 0;
}

【解惑】

我们有了printf和scanf为什么还要学习cin和cout呢,因为其可以自动识别变量的类型,相对来说就方便了很多,不用考虑太多。不过cin/cout相对于前者慢一些,在大量数据需要输入输出时就会有较大的时间差距。

3. 缺省参数

声明或者定义函数时为函数参数指定一个缺省值,当函数没有传递对应的参数时,就用缺省参数来代替(有点像备胎的感觉doge)

#include <iostream> 
using namespace std;

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

int main()
{
    Func(); //输出10
    Func(100); //输出100
    return 0;
}

【分类】

全缺省参数:所有形参都加上了缺省参数

void Func(int a = 10, int b = 20, int c = 30)
{
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl;
}

int main()
{
    Func(9, 8, 5);
    Func(9, 8);
    return 0;
}

半缺省参数:只有部分参数给缺省值

void Func(int a, int b = 20, int c = 30)
{
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl;
}

//错误写法
//void Func(int a = 10, int b, int c = 30)
//void Func(int a = 10, int b = 20, int c)
//void Func(int a = 10, int b, int c)

int main()
{
    Func(9);
    Func(9, 8);
    Func(9, 8, 5);
    return 0;
}

注意:

1. 半缺省参数只能从右往左给,不能跳跃给,也是为了避免传错参数,出现歧义

2. 缺省参数不能同时在定义和声明中出现,一般在声明中给

3. 缺省值必须是全局变量或常量

4. 函数重载

C++中允许在同一个作用域中出现参数列表不同(参数个数或类型不同)的同名函数,称这种现象为函数重载

【示例】

#include <iostream>
using namespace std;
​
//参数个数不同
void f1(int x, int y)
{
    cout << "void f1(int x, int y)" << endl;
}
​
void f1(int m)
{
    cout << "void f1(int m)" << endl;
}
​
//参数类型不同
void f2(int m)
{
    cout << "void f2(int m)" << endl;
}
​
void f2(double m)
{
    cout << "void f2(double m)" << endl;
}
​
//参数类型顺序不同,本质就是类型不同
void f3(int x, double y)
{
    cout << "void f3(int x, double y)" << endl;
}
​
void f3(double x, int y)
{
    cout << "void f3(double x, int y)" << endl;
}
​
int main()
{
    f1(10, 20);
    f1(10);
    cout << endl;
    f2(10);
    f2(1.0);
    cout << endl;
    f3(10, 1.0);
    f3(1.0, 10);
​
​
    return 0;
}

【原理】

C++的编译器会对函数进行修饰,一种函数变量类型对于一种编码,所以不同的变量类型或者个数对应不同的汇编代码,所以函数名相同并不影响其分别不同的函数。

而C语言中,相同的函数名是区分不开的。

(此部分需要对程序的翻译和执行部分有一定的了解,可以暂时跳过)

5. 引用

引用是对已经创建的变量起别名,操作符是&

【示例】

#include <iostream> 
using namespace std;

int main()
{
    int a = 1;
    int& b = a;

    cout << a << endl;
    cout << b << endl;
    //打印结果都是1

    cout << &a << endl;
    cout << &b << endl;
    //打印出来是同一个地址,也就意味着在同一个空间
    return 0;
}

结果如下:

所以当其中一个加的时候,另一个也加,效果如下:

注意:

1. 引用和实体的类型要相同,鲁迅和周树人都是人

2. 引用在定义时必须初始化

3. 一个变量可以多个引用,也就是可以多个别名

4. 引用一个实体就不能再引用其他的实体,鲁迅是周树人的别名,就不能再用“鲁迅”代指张三了

5. 引用不能作函数局部变量的返回值,因为返回值的空间在退出函数之后就销毁了,而引用与它共用一块空间,所以此时为非法访问空间。当然,如果是全局变量/函数外局部变量/静态变量/堆上变量也是可以的作为返回值的。

​​​​​​​

【使用方式】

1. 输出型参数

#include <iostream>
using namespace std;
​
void Swap1(int& x, int& y)
{
    int temp = x;
    x = y;
    y = temp;
} //节省拷贝的空间,在传大的对象时对比更加明显
​
void Swap2(int* m, int* n)
{
    int temp = *m;
    *m = *n;
    *n = temp;
} //需要额外开辟一块空间存临时变量
​
int main()
{
    int a = 1, b = 2;
    Swap1(a, b);
    cout << a << " " << b << endl;

    int c = 1, d = 2;
    Swap2(&c, &d);
    cout << c << " " << d << endl;
​
    return 0;
}

2. 函数返回值(注意返回局部变量时不可用)

#include <time.h>
#include <iostream>
using namespace std;

struct A
{ 
    int a[10000]; 
};

A a; 

A TestFunc1() 
{ 
    return a;
}

A& TestFunc2()
{ 
    return a;
}

int main()
{
    size_t begin1 = clock();
    for (size_t i = 0; i < 100000; ++i)
        TestFunc1();
    size_t end1 = clock();

    size_t begin2 = clock();
    for (size_t i = 0; i < 100000; ++i)
        TestFunc2();
    size_t end2 = clock();

    cout << "TestFunc1 time:" << end1 - begin1 << endl;
    cout << "TestFunc2 time:" << end2 - begin2 << endl;
    return 0;
}

这效率,赢麻了!

有小伙伴又要问了,引用这么香,谁还用指针呀?

那我们就得来看看指针和引用的区别了:【面试考点】

语法:

  1. 引用是别名,不开空间,指针是地址,需要开空间存地址
  2. 引用必须初始化,指针可以初始化也可以不初始化
  3. 引用不能改变指向,指针可以(不可替代的关键)
  4. 引用相对更安全,没有空引用,但是有空指针,容易出现野指针,但是不容易出现野引用
  5. sizeof(引用为引用类型的大小,指针为地址的大小)、++(引用实体+1,指针偏移一个类型的大小)、解引用访问(引用不用解引用)等方面的区别

底层:

汇编层面上,没有引用,都是指针,引用编译后也转换成指针了

总结:C++的引用,对指针使用比较复杂的场景进行一些替换,让代码更简单易懂,但是不能完全替代指针,因为引用定义后,不能改变指向

【常引用】

如果我需要一个不可被修改的别名,就会使用到常引用

//代码一:正常引用(权限平移)
int a = 10;
int& ra = a;
​
//代码二:会报错,本来我设的变量不可被改,但是你的引用可以改,相当于给它的权限过大了
const int b = 10;
int& rb = b;
​
//代码三:常引用,相当于创建了一个不可修改的别名(权限缩小)
int c = 10;
const int& rc = c;

//代码四:d转换成int需要生成临时变量,再将临时变量赋给rd引用,
//而临时变量是常量,所以rd要用常量引用,此代码没有const是编译错误的
double d = 3.14;
const int& rd = d;

6. 内联函数

一般来说,函数调用都会建立栈帧,而如果有方式可以避免栈帧的调用,可以大大提高运行的效率。

C++引入了一个关键字inline,以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开(函数调用替换为函数体),没有函数调用建立栈帧的开销,从而大大提升运行效率。

【示例】

inline int Add(int x, int y)
{
	return x + y;
}

int main()
{
	int ret = Add(3, 4);
	cout << ret << endl;
	return 0;
}

其实没什么好说的,就是在函数前加上inline。

不过,编译器会判断此代码是否大小合适,如果比较大的话还是会建立栈帧,避免在调用处展开导致程序膨胀。

注意:

1. 不能是递归的函数,且最好规模较小频繁调用的函数。

2. 不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

【拓展】

【面试考点】如果在头文件中包含了一个函数的声明和定义,导致出现链接错误,该如何处理?

1. 声明和定义分离

2. 用static修饰函数,链接属性只在当前文件可见,不会进符号表(大函数)

3. inline修饰,没有进符号表,不会出现链接冲突

有小伙伴就要问了,好像C语言里的宏也可以做到类似的效果(不建立栈帧就能调用)呀?

但是宏也是有缺点的,详细的内容可看这篇文章-链接

在C++中,有很多设计都可以替代宏:const,enum,inline

7. auto关键字

在C++中,有的类型的名字会很长,所以很容易会出错,而这就引出了auto关键字

这个关键字的作用就是自动识别类型

当然,除了用在比较长的类型名上,还可以用于for循环,这个也是C++特有的

示例如下:

int main()
{
    int array[] = { 1,2,3,4,5 };
    for (auto& e : array)
    {
        e *= 2;
    }
​
    for (auto e : array)
    {
        cout << e << " ";
    }
​
    return 0;
}

上面这段代码等价于:

int main()
{
    int array[] = { 1,2,3,4,5 };
    for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
    {
        array[i] *= 2;
    }
​
    for (int* p = array; p < array + sizeof(array) / sizeof(array[0]); p++)
    {
        cout << *p << " ";
    }
​
    return 0;
}

可见这里可以省去了不少的代码,不过要注意如果不是遍历数组就不能这么操作了

【注意点】

1. ​​​​​​​auto声明指针类型时,用auto和auto*没有区别,但用auto声明引用类型时必须加&

2. auto不能作为函数参数和返回值,也不能用来声明数组

8. 空指针nullptr

NULL可作常量0,也可作无类型指针的常量,

一般情况下,NULL会被编译器认为是0常量,但是我们想用它的时候往往是当作指针来用,为了避免会出现麻烦的情况,所以C++又设计了一个nullptr指针,就是表示指针空值,即(void*)0

这篇内容很多,可以收藏下来慢慢看~感谢大家的点赞和支持👍

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

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

相关文章

LeetCode 热题 100 | 链表(上)

目录 1 基础知识 1.1 空指针 1.2 结构体 1.3 指针访问 1.4 三目运算符 2 160. 相交链表 3 206. 反转链表 4 234. 回文链表 菜鸟做题第三周&#xff0c;语言是 C 1 基础知识 1.1 空指针 使用 nullptr 来判断是否为空指针&#xff1a; if (headA nullptr) …

鸿蒙开发有必要学吗?看完这篇再决定吧

在科技的潮流中&#xff0c;每一次新操作系统的诞生都是对旧秩序的挑战与新机遇的孕育。鸿蒙操作系统的出现&#xff0c;无疑是近年来科技界最引人注目的事件之一。自华为于2019年正式推出鸿蒙系统以来&#xff0c;这一我们自主研发的操作系统不仅在国内引起巨大反响&#xff0…

常见的6种软件测试用例设计方法

常见的软件测试用例设计方法&#xff0c;个人认为主要是下面这6种&#xff1a; 流程图法&#xff08;也叫场景法&#xff09;等价类划分法边界值分析判定表正交法错误推测法 这6种常见方法中&#xff0c;我分别按照定义、应用场景、使用步骤、案例讲解这4个部分进行讲解。 所…

MySQL查询数据(十)

MySQL查询数据&#xff08;十&#xff09; 一、SELECT基本查询 1.1 SELECT语句的功能 SELECT 语句从数据库中返回信息。使用一个 SELECT 语句&#xff0c;可以做下面的事&#xff1a; **列选择&#xff1a;**能够使用 SELECT 语句的列选择功能选择表中的列&#xff0c;这些…

不一样的味觉体验:精酿啤酒与烤肉的绝妙搭配

在繁华的都市生活中&#xff0c;人们总是在寻找那份与众不同的味觉享受。当夏日的微风轻轻拂过&#xff0c;你是否想过&#xff0c;与三五好友围坐在一起&#xff0c;拿着Fendi Club啤酒与烤肉的绝妙搭配&#xff0c;畅谈生活点滴&#xff0c;感受那份惬意与自在&#xff1f; F…

2401Idea用GradleKotlin编译Java控制台中文出乱码解决

解决方法 解决方法1 在项目 build.gradle.kts 文件中加入 tasks.withType<JavaCompile> {options.encoding "UTF-8" } tasks.withType<JavaExec> {systemProperty("file.encoding", "utf-8") }经测试, 只加 tasks.withType<…

基于单片机的智能燃气灶控制系统设计

摘要&#xff1a;针对传统燃气灶存在不能防干烧、不能进行温度检测、不能进行火力自动调节等问题&#xff0c;设计了一种基于单片机控制的智能燃气灶&#xff0c;它通过单片机进行控制&#xff0c;由开关模块、测温模块、语音播报模块、火力控制模块和防空烧模块五个模块组成&a…

Lazysysadmin

信息收集 # nmap -sn 192.168.1.0/24 -oN live.port Starting Nmap 7.94 ( https://nmap.org ) at 2024-01-30 21:10 CST Nmap scan report for 192.168.1.1 (192.168.1.1) Host is up (0.00075s latency). MAC Address: 00:50:56:C0:00:08 (VMware) Nma…

Flutter解析后台发来的jwt字段数据,了解jwt是否过期

前言 了解JWT是什么可以看这一篇博文 JWT&#xff08;JSON Web Token&#xff09;详解以及在go-zero中配置的方法-CSDN博客 流程 采用jwt_decoder库 添加至pubspec.yaml jwt_decoder: ^2.0.1 解析字段 查看是否过期 获取过期时间和token颁发的年龄

面试八股文(2)

文章目录 1.ArrayList和LinkedList区别2.HashMap和HashTable区别3.线程的创建方式4.Java中异常处理5.Java序列化中某些字段不想进行序列化&#xff1f;6.Java序列化7.静态方法和实例方法8.List、Set、Map三者区别9.ArrayList和Vector区别10.HashMap和HashSet区别 1.ArrayList和…

【C++】 C++入门— 基于范围的 for 循环

C 基于范围的for循环1 使用样例2 使用条件3 完善措施 Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&#xff01;下一篇文章见&#xff01;&#xff01;&#xff01; 基于范围的for循环 1 使用样例 使用for循环遍历数组&#xff0c;我们通常这么写&#xff1a; …

博云科技与中科可控全面合作,探索前沿金融科技新机遇

2024年1月26日&#xff0c;博云科技与中科可控在昆山高新区成功举办合作签约仪式。昆山市委常委、昆山高新区党工委书记孙道寻、中科可控董事长聂华、博云科技董事长花磊等领导出席了本次签约仪式。 中科可控将利用其在先进计算和智造领域的优势&#xff0c;为博云科技提供有关…

el-table添加(取消,确认)

点击添加输入添加项&#xff0c;但是不想添加了&#xff0c;就点击取消&#xff0c;但是在打开之前输入的数据还在&#xff0c;在点击取消的时候数据清空 页面 数据没有清空的时候&#xff0c;点击取消之后&#xff0c;在打开数据还在 数据清空之后&#xff0c;在打开数据是没…

寒假作业2月2号

第一章 命名空间 一&#xff0e;选择题 1、编写C程序一般需经过的几个步骤依次是&#xff08;C &#xff09; A. 编辑、调试、编译、连接 B. 编辑、编译、连接、运行 C. 编译、调试、编辑、连接 D. 编译、编辑、连接、运行 2、所谓数据封装就是将一组数据和与这组数据有关…

为期 90 天的免费数据科学认证(KNIME)

从 2 月 1 日开始&#xff0c;KNIME 官方将免费提供 KNIME 认证 90 天。 无论您是刚刚迈入数据科学领域、已经掌握了一些技术&#xff0c;还是正在构建预测模型&#xff0c;都可以参加为期 90 天的 KNIME 认证挑战赛&#xff0c;完成尽可能多的认证并获得数据科学技能免费认证。…

嵌入式系统学习(一)

嵌入式现状&#xff08;UP经历&#xff09;&#xff1a; 大厂的招聘要求&#xff1a; 技术栈总结&#xff1a; 产品拆解网站&#xff1a; 52audio 方案查询网站iotku,我爱方案网&#xff0c; 主要元器件类型&#xff1a;

二分查找------蓝桥杯

题目描述&#xff1a; 请实现无重复数字的升序数组的二分查找 给定一个元素升序的、无重复数字的整型数组 nums 和一个目标值 target&#xff0c;写一个函数搜索 nums 中的target&#xff0c;如果目标值存在返回下标 (下标从0 开始)&#xff0c;否则返回-1 数据范围: 0 < l…

哇塞,这几种Java文件读写性能差距居然这么大?

引言 这是一篇性能比较的文章&#xff0c;不分析实现原理。主要是对比Java几种常见的文件写入方式 测试代码 主要分析Stream、StreamBuffer和mmap三种方式&#xff0c;对应的大致代码如下 public static void testBasicFileIO(List<Persona> list, String path) throw…

Flume搭建

压缩包版本&#xff1a;apache-flume-1.9.0-bin.tar 百度盘链接&#xff1a;https://pan.baidu.com/s/1ZhSiePUye9ax7TW5XbfWdw 提取码&#xff1a;ieks 1.解压 tar -zxvf /opt/software/apache-flume-1.9.0-bin.tar.gz -C /opt/module/ 2. 修改文件名 [rootbigdata1 opt]…

Chatglm3+langchain智能对话,本地文本库构建问答,图片文本库构建与问答搜索

Chatglm3langchain 主要功能&#xff1a; 调用语言模型将不同数据源接入到语言模型的交互中允许语言模型与运行环境交互 Langchain应用场景 **1. 文档问答&#xff1a;**常见的Langchain用例。在特定文档上回答问题&#xff0c;仅利用这些文档中的信息来构建问答答案&#…