【C++】入门与过渡
【C++】入门与过渡
注:本文为学习笔记,只记录了一些重点,有些比较简单的内容做了省略
一、命名空间
解决问题:对标识符的名称进行本地化,以避免命名冲突或名字污染
使用方法:
- 命名空间名称及作用域限定符
::
,前面没有命名空间表示全局 - 使用using将命名空间中成员引入
- 使用using namespace 命名空间名称引入
注意:
- 命名空间可以嵌套
- 同名的命名空间将被合并
- 命名空间影响的是编译查找规则。使用命名空间后,查找范围为:局部、全局、命名空间
- 一般练习用哦namespace,实际项目最好不用
示例:
std::cout << "hello world";
using std::cout;
using namespace std;
二、输入输出(cin/cout)
使用:
#include <iostream>
int main() {
std::cout << "input: ";
int a = 0;
std::cin >> a;
std::cout << "output: " << a << std::endl;
return 0;
}
注意:取消缓冲区同步语句 std::ios::sync_with_stdio(false)
三、缺省参数
作用:缺省参数是声明或定义函数时为函数的参数指定一个默认值
分类:
- 全缺省参数
void test(int a = 1, int b = 2, int c = 3)
- 部分缺省参数
void test(int a, int b = 1, int c = 2)
注意:
- 半缺省参数必须从右往左依次来给出,不能出现间隔
- 缺省参数不能在函数声明和定义中同时出现。若声明和定义进行分离,需要使用缺省参数,必须在声明中给出。
- 缺省值必须是常量或者全局变量
四、函数重载
作用:C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数、类型、顺序)不同
使用
int Add(int left, int right);
int Add(int left, int right,int temp);
int Add(int left, int right);
double Add(double left, double right);
double Add(double left, int right);
double Add(int left, double right);
注意:
- 类型将自动识别
- 会影响编译速度,但不会影响运行速度
- 同一作用域
- double与float的传参区分需要注意后缀有没有f
- 可以从函数名修饰的规则来理解重载,返回值不同不能构成重载
原理补充:
- c++函数名修饰规则,从而区别不同函数,不同平台修饰规则是不同的。
- c++将会用修饰以后函数名去寻找函数的地址
五、引用
作用
给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间
使用
-
定义,相当于给已存在变量取了一个别名,用不同的变量名来标识同一块地址空间;
int a = 0; int& b = a;
-
输出型参数,此时形参的改变会影响实参;
void swap(int* p1, int* p2); void swap(int& r1, int& r2);
-
传引用返回,出了作用域返回的变量还在。调用函数栈帧的销毁,不影响返回值的生命周期;
如果函数返回时,出了函数作用域,如果返回对象还未还给系统,则可以使用引用返回,如果已经还给系统了,则必须使用传值返回。多用于:静态变量、全局变量、上一层栈帧、堆区等。
// 引用返回 1、减少拷贝 2、调用者可以修改返回对象 int& PosAt(AY& ay, int i){ return ay.a[i]; } int main(){ int ret = Count(); AY ay; for (int i = 0; i < N; ++i){ PosAt(ay, i) = i*10; } for (int i = 0; i < N; ++i){ cout << PosAt(ay, i) << " "; } cout << endl; return 0; }
注
-
区分引用和取地址,类型+&为引用,&+变量为取地址
-
引用定义时必须初始化
-
一个变量可以存在多个引用
-
引用一旦引用一个实体,不能再引用其他实体
-
值和引用的作为返回值类型的性能比较下,引用的作为返回值性能可能更优秀。
-
常引用:赋值/初始化时,权限可以不变或者缩小,但是不能放大(指针同理)
临时变量具有常性,函数返回为临时变量、类型转换(中间会产生临时变量),也只能用常引用
const int a = 2; //int& b = a; 错误 const int& b = a; //正确
指针和引用的区别
- 语法概念:引用没有开空间,指针开辟了空间并存入了地址。引用在语法的层面上是变简单了
- 底层实现:也是开辟了一个空间,将有效地址写入。从汇编上看引用也是用指针实现的
- 引用必须初始化,指针没有要求
- 引用一个实体后,不能再引用其他实体,指针没有要求
- 没有NULL的引用,但有空指针
- sizeof的含义不同
- 自增自减的意义不一样
- 有多级指针,但是没有多级引用
- 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
- 引用比指针使用起来相对更安全
六、内联函数
定义:以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率。
使用
inline void test(int i){
cout << i << endl;
}
注意
- 替换宏函数:宏的缺点是纯粹简单的替换,无法调试,没有安全的类型检查并且在有些场景中非常的复杂
- 因此cpp推荐使用const和enum替换宏常量,inline替代宏函数
- 在使用inline后,就不会建立函数栈帧(需要在release模式下才能观察到)
- 是一种以空间换时间的做法,省去调用函数额开销,但是如果存在循环将可能造成空间浪费,因为会在每处调用处进行指令展开
- 编译器会自动优化,如果定义为inline的函数体内有循环/递归等等,编译器优化时会忽略掉内联
- inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到(可以直接在.h文件里面直接定义)
- 可以在同一个项目的不同源文件内定义函数名相同但实现不同的inline函数,因为inline函数会在调用的地方展开,所以符号表中不会有inline函数的符号名,不存在链接冲突。
七、auto关键字
作用:
- 编译器自动推导变量类型,作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得
- 当类型很长时,可以简化代码
使用
-
自动判断类型
int a = 10; auto b = a;
-
范围for 意义和使用:自动依次取数组中数据赋值给e对象,自动判断结束
注意:for循环迭代的范围必须是确定的;迭代的对象要实现++和==的操作
void test(){ int array[] = { 1, 2, 3, 4, 5 }; for(auto& e : array) e = 1; for(auto e : array) cout << e << " "; return 0; }
注意
- 缺点:无法显示获取变量的类型
auto e;
无法通过编译,使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。auto*
与auto&
,分别限定了必须为指针和引用- 同一行定义多个变量:当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量
- 不能使用的场景:不能作为函数的参数,不能用于声明数组
八、空指针
NULL与nullptr的区别:
-
NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量
#ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif #endif
-
在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的
-
在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同
原文地址:https://blog.csdn.net/qq_66725576/article/details/135560420
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!