C++入门

1.C++关键字

C++共63个关键字

例如:auto的作用是自动识别变量类型

当变量名字比较长的时候,就比较方便。

2.命名空间

使用命名空间的目的是防止产生命名冲突和名字污染。

C语言没办法处理这种命名冲突。所以在C++中引入了命名空间。

2.1 命名空间格式

定义命名空间,需要用到namespace关键字,后面跟命名空间的名字。

命名空间里面可以定义函数/变量/结构体:

命名空间也可以嵌套:

注:在同一个工程中,同一个名字的命名空间会被合并为一个。

2.2 命名空间的使用

那么命名空间怎么使用呢?比如:

对于上面的命名空间,一共存在三种调用方式:

1.加命名空间以及作用域限定符

2.使用using将命名空间中的成员引入

3.使用using namespace将命名空间名称引入

3.C++输入输出

注:cout和cin是全局的流对象,endl是特殊的C++符号,都包含在<iostream>中。

可以自动识别变量的类型。

4.缺省参数

4.1 缺省参数概念

缺省参数是声明或定义函数时为函数的参数指定一个缺省值,在调用函数时,如果没有指定实参就采用该形参的缺省值,否则使用指定的形参。

4.2 缺省参数分类

1.全缺省参数

2.半缺省参数

注:1.半缺省参数只能从左向右给,不能间隔着给。

       2.缺省参数不能在函数定义和声明中同时存在。

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

5.函数重载

1.

函数重载是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这

些同名函数的形参列表(参数个数类型类型顺序)不同,常用来处理实现功能类似数据类型

不同的问题。

2.C++支持函数重载而C语言不支持函数重载的原因。

C语言中都是同名函数,没有办法区分,而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。

6.引用

6.1 引用的概念

引用不是定义一个新变量,而是给已有的变量起一个新的名字,编译器不会再单独开空间,与原来变量共同使用同一块空间。

6.2 引用特性

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

2.一个变量可以有多个引用。

3.引用一旦引用一个实体,就不能再引用其他实体。

6.3 常引用

1.权限的平移

变量a是int类型,可读可写,a的别名ra也是可读可写的。

#include<iostream>
using namespace std;
 
int main() {
	int a = 10;
	int& ra = a;
	ra++;
	cout << a << endl;

2.权限的放大

下面这段代码中,变量b有了const修饰,就变成了可读不可写,而rb是b的别名,是可读可写的,所以说这段代码是错误的。

const int b = 20;
int& rb = b;

正确的写法:

//正确写法
	const int& rb = b;

3.权限的缩小

变量c是int类型,是可读可写的,而rc是c的别名,它的权限是可读不可写,这样是可以的。

 
	int c = 100;
	const int& rc = c;

rc只能读,不能改变,但是变量c可以,如果变量c改变,那么rc会跟着变。(不能通过rc来改变c)。

6.4 引用类型转换

由double类型转换成int类型,会先产生一个临时变量,然后在转换成整形,临时变量具有常性,仅仅可读。

int main() {
	double d = 15.56;
	//类型转换
	int i = d;	//d产生临时变量,是临时变量转换为整型  i==15
 
	//int& j = d;//报错	//也是d产生临时变量,而临时变量具有常性,int& j权限为可读可写,为放大
	const int& k = d; //正确
	return 0;
}

例:

//值传递
void Func(int x) {
 
}
 
 
int main(){
int a = 10;
	const int b = 20;
	int& ra = a;
	const int& rb = b;
	Func(a);
	Func(b);
	Func(ra);
	Func(rb);
}

在上面这段代码中,所有函数调用都成功。在这里没有权限的概念(只有在引用和指针的时候有),因为传值只是对变量的一份临时拷贝。

    void Func2(int& x) {
 
    }    
 
    int main(){
    int a = 10;
	const int b = 20;
	int& ra = a;
	const int& rb = b;
    
    Func2(a);
	Func2(b);    //报错
	Func2(ra);    
	Func2(rb);    //报错
 
    }

这里报错是因为权限的问题,b是只读,而Func2是可读可写,rb同理,我们只需改为void Func2(const int&x)。

6.5 使用场景

1.做参数

2.做返回值

int& Count()
{
   static int n = 0;
   n++;
   // ...
   return n;
}

6.6 传值和传址的比较

传值实际上传的是实参的临时拷贝,所以说消耗极大。

6.7 引用和指针的区别 

引用实际上就是一个别名,并没有单独开内存空间,与实体共用一块空间。

但是在底层,引用其实和指针一样,都有空间。

引用和指针的不同点:
1.引用定义的是一个变量的别名,而指针存储的是变量的地址。

2.引用在定义时必须要初始化,而指针可以使空指针。

3.引用在初始化是引用一个实体后,不能在引用其他实体,而指针可以任意指向同一类型实体。(删除链表节点)。

4.引用加一就是实体加一,而指针加一本质上是向后偏移一个类型的大小。

5.指针需要显示解引用,引用编译器自己处理。

7.内联函数

7.1 概念

用inline修饰的函数叫做内联函数,编译时会在调用内联函数的地方自动展开,不需要建立函数栈帧,能够提高程序运行的效率。

call在这里实际是跳转去调用函数,建立了函数栈帧。

而在这里直接用函数体替换了函数调用。

7.2 特性

1.inline是一种以空间换时间的做法,缺点:可能会使目标文件变大,优点:少了调用,提高效率。

2.一般来说,对于函数规模较小(函数不是很长)且频繁调用的,可以用inline修饰。

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

面试题:

宏的优缺点?

优点:

1.增强代码的复用性。

2.提高性能。

缺点:
1.不方便调试宏。

2.导致代码的可读性差,可维护性差。

3.没有类型安全的检查。

C++有哪些可以代替宏?
1.常量定义 换用const enum

2.短小函数定义 换用inline

8.auto关键字(C++11)

8.1 auto简介

auto可以自动识别类型,相当于(int ,char...)

当名字比较长时,auto就很有用。

注:auto必须初始化。

8.2 auto的使用细则

1.auto于指针和引用结合

当auto声明指针时,auto和auto*没有任何区别。但是声明指针时,必须用auto&。

int main()
{
    int x = 10;
    auto a = &x;
    auto* b = &x;
    auto& c = x;
    cout << typeid(a).name() << endl;
    cout << typeid(b).name() << endl;
    cout << typeid(c).name() << endl;
    *a = 20;
    *b = 30;
     c = 40;
    return 0;
}

2.在同一行声明多个变量

void TestAuto()
{
    auto a = 1, b = 2; 
    auto c = 3, d = 4.0;  // 该行代码会编译失败,因为c和d的初始化表达式类型不同
}

auto最优势的是C++11的新型for循环和lambda表达式混合使用。

8.3 auto不能使用的情况

1.auto不能作为函数的参数

// 此处代码编译失败,auto不能作为形参类型,因为编译器无法对a的实际类型进行推导
void TestAuto(auto a)
{}

2.auto不能用来声明数组

void TestAuto()
{
    int a[] = {1,2,3};
    auto b[] = {4,5,6};
}

9.基于范围的for循环(C++11)

9.1 范围for的语法

在C++11中,for循环后的括号中以 : 为界,前半部分是部分是范围内变量的名称,后半部分是变量的范围。

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

注:与普通循环类似,可以用continue来结束本次循环,也可以用break提前跳出循环。

9.2 范围for的使用条件

1.for循环迭代的范围必须是确定的。

2.迭代的对象要实现++和==的操作。

10.指针空值nullptr(C++11)

在 C/C++编程习惯中,如果一个指针没有合法的指向,我们基本都是按照如下方式初始化:

void TestPtr()
{
int* p1 = NULL;
int* p2 = 0;
// ……
}

NULL 实际是一个宏,在传统的 C 头文件 (stddef.h) 中,可以看到如下代码:

#ifndef NULL
#ifdef __cplusplus
#define NULL   0
#else
#define NULL   ((void *)0)
#endif
#endif

可以看到, NULL 可能被定义为字面常量 0 ,或者被定义为无类型指针 (void*) 的常量 。不论采取何种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦,比如:

void f(int)
{
 cout<<"f(int)"<<endl;
}
void f(int*)
{
 cout<<"f(int*)"<<endl;
}
int main()
{
 f(0);
 f(NULL);
 f((int*)NULL);
 return 0;
}

程序本意是想通过 f(NULL) 调用指针版本的 f(int*) 函数,但是由于 NULL 被定义成 0 ,因此与程序的初衷相悖。
在 C++98 中,字面常量 0 既可以是一个整形数字,也可以是无类型的指针 (void*) 常量,但是编译器默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强转 (void*)0;

注意:
1. 在使用 nullptr 表示指针空值时,不需要包含头文件,因为 nullptr 是 C++11 作为新关键字引入
的 。
2. 在 C++11 中, sizeof(nullptr) 与 sizeof((void*)0) 所占的字节数相同。
3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用 nullptr 。

因作者能力有限,以上仅供参考,如有问题请大家批评指正。创作不易,希望大家多多支持 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dddyy.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值