C++开始

简介: C++开始

C++开始

1. C++ 关键字

C++98里共63个,其中32个是C语言的。现在最新版本有68个。

2. 命名空间(namespace)

避免命名冲突和名字污染。在大型工程中变量/函数非常多,每一个模块都有大量的文件,大量的变量/函数/结构体/…,这时非常容易引起命名冲突。

引入命名空间就是解决命名冲突,不同命名空间中的变量可以一样。(docker中的隔离性!!) 一个命名空间就是一个新的作用域。

域作用限定符::: , A:: , B:::: (默认的是全局域)

#include <iostream>
namespace A
{
  int a = 10;
  int b = 20;
}
int main()
{
  int a = 1;
  int b = 2;
  // 这个作用域里的a和b
  std::cout << a + b << std::endl;
  // 命名空间A里的a和b
  std::cout << A::a + A::b << std::endl;
  return 0;
}
// 把 std(标准库) 里的变量全部放出来
using namespace std;
// 只放出来常用的
using std::cout;
using std::endl;

几点注意:

  1. 命名空间可以嵌套定义。
  2. 一个工程中有相同的命名空间时会合并。
  3. 命名空间只能在全局声明,不能在main函数里。
  4. 命名空间中的变量本质上还是全局的变量,只是使用命名空间进行隔离。

3. 输入输出

这两个运算符涉及到==运算符的重载。==正是因为重载,他们才可以自动识别类型。

// << 流插入
std::cout << "hello world" << std::endl;
// >> 流提取
int a, b;
cin >> a >> b;

4. 缺省参数

在函数形参那里可以指定一个缺省值,当实参那里没有传参数时就使用这个缺省参数,实参传了参数就用传过来的那个参数。

// 全缺省
void func(int a = 10, char ch = 's')
{
  // ...
}
// 半缺省
void func2(int a, int b, char ch = 's')
{
  // ...
}
int main()
{
  // 都可以
  func();
  func(1);
  func(1, 'a');
  func2(1, 2);
  func(1, 2, 'a');
}
  1. 可以全缺省,也可以半缺省(缺省一部分形参),但是半缺省时必须从最后一个参数开始顺序向前开始缺省!!就是从右向左依次给缺省值。(因为参数是从左往右依次传的)
  2. 当**一个函数声明和定义分开时,不能同时给缺省值!!**编译器不知道听谁的。这个时候应该是声明的时候写好缺省值,定义的时候不写缺省。(经过检验,在VS和Linux下同时给缺省是可以的,以声明的值为准!)
  3. 给定的缺省值只能是常量或全局变量。

5. 函数重载(重点)

在同一个作用域中可以定义多个同名的函数,但是函数的参数列表(参数个数/参数类型)必须不同,叫做函数重载。

C++支持重载的原因(面试题)

1. 程序的编译链接过程(预编译->编译->汇编->连接)
  1. 预处理(预编译):进行头文件展开,宏替换,条件编译,去掉注释…
  2. 编译:进行语法检查,语义分析,词法检查… 最终生成汇编代码。
  3. 汇编:形成符号表(函数名和对应的地址之间的映射),最终生成二进制文件。
  4. 连接:合并符号表,并进行符号表的重定位,就是将各个文件里只有函数声明,没有具体定义的那些函数,去符号表查找,找到其具体的地址!! 最终生成可执行文件(.o)。
2. C++支持重载具体原因

C++编译器(g++)在编译时会对函数名进行修改:

// 如下
Printf(int a, double b) -> _Z5Printid

具体修改规则(Linux下):_Z + 函数名长度(协议) + 函数名 + 所有参数类型缩写

这样就可以将重载的函数区分开。而C编译器(gcc)在编译时不会对函数名做修改,相同的函数名就无法区分,也就不能支持重载。

Linux下反汇编:
objdump -S[-c -t ....] filename > filename.txt
3. extern “C”

在实际中,可以使用C语言调用C++的动静态库(多个 .o 打包),也可以使用C++调用C语言的动静态库。但是:==C动静态库中编译后的函数名是没有经过更改的原始的函数名,而C++的动静态库中编译后的函数名是经过编译器修改后的函数名!==这和C/C++项目本身的编译规则是不一样的,这时就会导致链接错误----在链接时找不到符号表中对应的函数名!

这时就可以使用 extern "C" 来解决。

C++调用C

修改这个C++文件/项目

// 在C++文件中 加这个extern "C"后{}内的内容就会以C语言的规则编译(不修改函数名)
// 这样就可以避免C++编译时修改函数名而导致链接时在符号表中找不到对应的函数
extern "C"
{
  // 这个库里文件就会以C的方式编译,不修改函数名
  #include "/home/c_lib/.... .h"
}
C调用C++

C++的动静态库进行修改!!都是对C++的那一方进行修改。

利用条件编译!条件编译在跨平台方面非常有用!!

// 在C++库文件中(头文件)
#ifdef __cplusplus  // 在C++文件中默认有这个定义
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif
// 这些函数声明在C++库文件中就会以C的方式编译,不会对函数名做修改!
// 而在C的项目中包含这个头文件,展开后 EXTERN_C 是空!!也不会有任何问题!
EXTERN_C 函数声明
EXTERN_C 函数声明
EXTERN_C 函数声明
......

==本质就是为了做到在C++中以C的方式编译,同时不影响C包含C++的头文件而出错!!==或者这样也可以:

// 本质就是为了做到在C++中以C的方式编译,同时不影响C包含C++的头文件而出错!!
#ifdef __cplusplus
extern "C"
{
#endif
  函数声明
  函数声明
  函数声明
  // .....
#ifdef __cplusplus 
}
#endif

这时C++库中就不能使用函数重载了!!因为以C的方式编译不修改函数名,不支持重载!

6. 引用

1. 基本概念

就是给一个变量起别名。常用作函数形参函数返回值减少参数拷贝带来的消耗(函数调用会将实参拷贝到形参)。

做函数返回值时要特别注意一下,如果返回的变量在出了函数作用域后就销毁了,那就会有类似野指针的问题!(引用的对象销毁了!)

函数返回值问题:函数的返回值并不是直接返回的,而是先将返回值拷贝到一个临时变量(一般临时变量有常属性)。当返回值比较小时就可以拷贝到寄存器中;当返回值很大时会在 调用函数 建立栈帧的时候就提前开辟好这个空间!然后出了函数作用域这个返会的变量可能被销毁,所以再将这个临时变量拷贝到接收返回值的变量中!!

这就导致中间多了一步拷贝,当返回值比较大时效率很低!传引用返回就可以提高效率,直接就返回这个变量的别名(就是这个变量)。但是要求函数返回之后这个变量还在,没有被销毁!

**常引用:**这个还是很常用的,可以接收变量,常量,隐式类型转换等类型。

void TestConstRef()
{
  const int a = 10;
  // int& ra = a; // 该语句编译时会出错,a为常量
  const int& ra = a; // 可以
  // int& b = 10; // 该语句编译时会出错,10为常量
  const int& b = 10;  // 可以
  double d = 12.34;
  // int& rd = d; // 该语句编译时会出错,类型不同
  // 这个可以!!但是 rd 已经不是d这个变量的引用了!而是会产生一个int类型的临时     变量,rd是那个临时变量的引用。
  const int& rd = d;  // 这个留意一下!!
}

引用的几点注意:

  1. 引用在定义的时候必须初始化。
  2. 一旦引用了某一个实体,就不能改变,一直作为他的引用!
  3. 引用在语法层面就是一个别名,没有独立的空间,但是底层还是指针!!
2. 指针和引用的区别:
  1. 没有NULL引用,但是有NULL指针。
  2. sizeof(引用)大小是所引用类型的大小,sizeof(指针)在32位平台下是4字节。
  3. 引用进行加减操作是对本体进行加减,指针进行加减操作是向后/前 偏移一个类型大小。

7. 内联函数(inline)

使用关键字inline修饰的函数叫做内联函数,在编译时会直接在调用内联函数的地方把函数体展开,就不需要建立栈帧,进行传统的函数调用了!!提高运行效率(空间换取时间)

  1. 适用于频繁调用的短小函数(非递归的)。
  2. inline也只是一个建议,具体编译器会不会采用是不确定的!
  3. inline函数不能声明和定义写到不同的文件中!会有链接错误:定义内联函数的文件在生成 .o 目标文件时在符号表里不会生成该函数的地址(因为是内联函数),这样在链接的时候就找不到该函数了。
inline Add(int a, int b)
{
  return a + b;
}

在C语言中使用宏来做到这一点。宏的缺点:

  1. 不支持调试。
  2. 没有类型安全检查。

8. auto关键字

自动进行类型推导。

1. auto不能推导的场景

  1. 函数形参的类型不能用auto (C++20 以后也可以了)
  2. 函数返回值不能是auto
  3. auto不能直接用来声明数组。
// 获取变量类型
int a = 10;
cout << typeid(a).name() << endl;

9. 范围 for

// 自动遍历
for(auto& e : arr)
  cout << e << endl;

10. nullptr

空指针。更推荐!

#ifndef NULL
#ifdef __cplusplus
#define NULL 0         // 在C++中,NULL就是0
#else
#define NULL ((void *)0)
#endif
#endif

NULL是一个宏,C++中NULL就是 0,是一个整型,这就可能会有问题。比如:

void f(int)
{
  cout<<"f(int)"<<endl;
}
void f(int*)
{
  cout<<"f(int*)"<<endl;
}
int main()
{
  f(0);               // f(int)
  f(NULL);            // f(int)  但是直观来看,这里应该是 f(int*)
  f((int*)NULL);      // f(int*)
  return 0;
}

nullptr 是一个关键字!使用更安全。

NULL是一个宏,C++中NULL就是 0,是一个整型,这就可能会有问题。比如:

void f(int)
{
  cout<<"f(int)"<<endl;
}
void f(int*)
{
  cout<<"f(int*)"<<endl;
}
int main()
{
  f(0);               // f(int)
  f(NULL);            // f(int)  但是直观来看,这里应该是 f(int*)
  f((int*)NULL);      // f(int*)
  return 0;
}

nullptr 是一个关键字!使用更安全。

最后挂个链接,欢迎一起学习,一起进步!https://xxetb.xet.tech/s/4G6TWG

相关文章
|
开发者 容器 流计算
社区编辑部特别策划:每周精选活动和开发者彩蛋!
阿里云开发者社区编辑部特别策划,海量免费电子书,最新直播在线追,每周都有彩蛋哦!
19616 0
社区编辑部特别策划:每周精选活动和开发者彩蛋!
|
SQL 关系型数据库 Java
JDBC驱动下载汇总
在使用JDBC连接数据库的时候,一般都要求有相应数据库的JDBC驱动程序,这些数据库的JDBC驱动程序一般都是数据库厂商开发的,但是有些,例如MS之类的很久都,没有为它的SQL Server开发相应的JDBC驱程,所以要使用第三方公司开发的驱动程序(不过现在微软已经为SQL Server开发了JDBC驱动程序),为了使得大家方便学习,这里给出一些主要的数据库相应的JDBC驱动下载地址和相应的操作方法,希望能够对大家有所帮助。
1919 0
|
19小时前
|
存储 运维 安全
云上金融量化策略回测方案与最佳实践
2024年11月29日,阿里云在上海举办金融量化策略回测Workshop,汇聚多位行业专家,围绕量化投资的最佳实践、数据隐私安全、量化策略回测方案等议题进行深入探讨。活动特别设计了动手实践环节,帮助参会者亲身体验阿里云产品功能,涵盖EHPC量化回测和Argo Workflows量化回测两大主题,旨在提升量化投研效率与安全性。
云上金融量化策略回测方案与最佳实践
|
14天前
|
人工智能 自动驾驶 大数据
预告 | 阿里云邀您参加2024中国生成式AI大会上海站,马上报名
大会以“智能跃进 创造无限”为主题,设置主会场峰会、分会场研讨会及展览区,聚焦大模型、AI Infra等热点议题。阿里云智算集群产品解决方案负责人丛培岩将出席并发表《高性能智算集群设计思考与实践》主题演讲。观众报名现已开放。
|
6天前
|
自然语言处理 数据可视化 API
Qwen系列模型+GraphRAG/LightRAG/Kotaemon从0开始构建中医方剂大模型知识图谱问答
本文详细记录了作者在短时间内尝试构建中医药知识图谱的过程,涵盖了GraphRAG、LightRAG和Kotaemon三种图RAG架构的对比与应用。通过实际操作,作者不仅展示了如何利用这些工具构建知识图谱,还指出了每种工具的优势和局限性。尽管初步构建的知识图谱在数据处理、实体识别和关系抽取等方面存在不足,但为后续的优化和改进提供了宝贵的经验和方向。此外,文章强调了知识图谱构建不仅仅是技术问题,还需要深入整合领域知识和满足用户需求,体现了跨学科合作的重要性。
|
1月前
|
存储 人工智能 弹性计算
阿里云弹性计算_加速计算专场精华概览 | 2024云栖大会回顾
2024年9月19-21日,2024云栖大会在杭州云栖小镇举行,阿里云智能集团资深技术专家、异构计算产品技术负责人王超等多位产品、技术专家,共同带来了题为《AI Infra的前沿技术与应用实践》的专场session。本次专场重点介绍了阿里云AI Infra 产品架构与技术能力,及用户如何使用阿里云灵骏产品进行AI大模型开发、训练和应用。围绕当下大模型训练和推理的技术难点,专家们分享了如何在阿里云上实现稳定、高效、经济的大模型训练,并通过多个客户案例展示了云上大模型训练的显著优势。
|
2天前
|
人工智能 容器
三句话开发一个刮刮乐小游戏!暖ta一整个冬天!
本文介绍了如何利用千问开发一款情侣刮刮乐小游戏,通过三步简单指令实现从单个功能到整体框架,再到多端优化的过程,旨在为生活增添乐趣,促进情感交流。在线体验地址已提供,鼓励读者动手尝试,探索编程与AI结合的无限可能。
|
2天前
|
人工智能 自然语言处理 前端开发
从0开始打造一款APP:前端+搭建本机服务,定制暖冬卫衣先到先得
通义灵码携手科技博主@玺哥超carry 打造全网第一个完整的、面向普通人的自然语言编程教程。完全使用 AI,再配合简单易懂的方法,只要你会打字,就能真正做出一个完整的应用。
951 12
|
6天前
|
Cloud Native Apache 流计算
PPT合集|Flink Forward Asia 2024 上海站
Apache Flink 年度技术盛会聚焦“回顾过去,展望未来”,涵盖流式湖仓、流批一体、Data+AI 等八大核心议题,近百家厂商参与,深入探讨前沿技术发展。小松鼠为大家整理了 FFA 2024 演讲 PPT ,可在线阅读和下载。
3149 10
PPT合集|Flink Forward Asia 2024 上海站
|
19天前
|
人工智能 自然语言处理 前端开发
100个降噪蓝牙耳机免费领,用通义灵码从 0 开始打造一个完整APP
打开手机,录制下你完成的代码效果,发布到你的社交媒体,前 100 个@玺哥超Carry、@通义灵码的粉丝,可以免费获得一个降噪蓝牙耳机。
5881 16