c++入门

目录

前言:

c++作为面向对象的语言与c的简单区别:

 c++的打印与输出:

命名空间

缺省参数:

 半缺省参数

全缺省参数

函数重载:

 1.参数类型不同:

2.参数个数不同:

3. 参数类型顺序不同:

错误举例:

 引用

引用的举例: 

 注意事项:

引用做返回值 

 引用做参数:

 两者的优点:

权限  

内联函数:

test.c文件 

test.h文件

 关键字auto

空指针nullptr


前言:

c++作为面向对象的语言与c的简单区别:

c语言作为面向过程的语言还是跟c++有很大的区别的,

比如说一个简单的五子棋的实现

对于c语言

面向过程的设计思路是首先分析解决这个问题的步骤:

(1)开始游戏(2)黑子先走(3)绘制画面(4)判断输赢(5)轮到白子(6)绘制画面(7)判断输赢(8)返回步骤(2) (9)输出最后结果。

但对于c++就不一样了,

在下五子棋的例子中,用面向对象的方法来解决的话,首先将整个五子棋游戏分为三个对象:

(1)黑白双方,这两方的行为是一样的。

(2)棋盘系统,负责绘制画面

(3)规则系统,负责判定犯规、输赢等。

然后赋予每个对象一些属性和行为

具体想要了解的可以直接跳转面向过程 VS 面向对象 - 知乎 (zhihu.com)

 c++的打印与输出:

需要注意的是我们需要自己写上一行代码:std是c++标准库的命名空间

using namespace std;

在c语言中我们使用printf打印,在c++中我们可以使用cout<<"hello world"<<endl;进行打印;

#include<iostream>
using namespace std;

int main()
{
	cout << "hello world" << endl;
	return 0;
}

 这里的iostream就跟c语言中的include差不多,是头文件,只是c++为了与c做区别,统一是不带.h

这里的c是控制台console的缩写   out是控制台输出    endl就是换行

对应的输入就是cin


命名空间

有的时候,当我们遇到变量重名时,无法解决使用哪个变量,这里我们引申命名空间来解决这个问题,这一点也是很明确解决了c语言的一个大毛病,就是比如我们自己定义了一个变量a,但是有一个库函数,里面有一个自带的a,这时候就会引发冲突,这一点在c++有了明确解决。

#include<iostream>
using namespace std;
namespace _name
{
	int rand = 1;
}
int main()
{
	cout << rand << endl;//库函数自带的rand
	cout << _name::rand << endl;//我们自己定义的rand
	return 0;
}

区别还是很明显的,也很好理解,也很方便。 

 需要注意的是,如果在前面加了一行using

就会有语法错误,这是因为,如果引用了using _name 

就会这样,为什么呢?

 这是因为在这段代码中,使用了命名空间_name来定义一个变量rand,并且使用了using namespace _name来引入该命名空间。由于库函数std中也有一个名为rand的函数,因此在输出rand时会产生歧义,编译器无法确定到底是使用库函数中的rand还是命名空间_name中的rand。

我们可以前面加一个std::

#include<iostream>
using namespace std;
namespace _name
{
	int rand = 1;
}
using namespace _name;
int main()
{
	cout << std::rand << endl;//库函数自带的rand
	cout << _name::rand << endl;//我们自己定义的rand
	return 0;
}

这样就正确了;


缺省参数:

缺省参数的存在,在c++中实在是妙,这解决了我们很多问题,比如说c语言中函数传参时,我们不知道传什么,但又不得不去传这一点在缺省参数可以完美解决,缺省参数分为两种

  1. 全缺省参数

  2. 半缺省参数

 半缺省参数

int add(int a, int b = 1)
{
	return a + b;
}
int main()
{
	int ret1 = add(1, 2);//实现了1+2
	int ret2 = add(1);//实现了1+1
	cout << "ret1=" << ret1 << endl;
	cout << "ret2=" << ret2 << endl;
	return 0;
}

还是很好理解的 

全缺省参数

int add(int a = 5, int b = 1)
{
	return a + b;
}
int main()
{
	int ret1 = add(1, 2);//实现了1+2
	int ret2 = add(1);//实现了1+1
	int ret3 = add();//实现了5+1
	cout << "ret1=" << ret1 << endl;
	cout << "ret2=" << ret2 << endl;
	cout << "ret3=" << ret3 << endl;
	return 0;
}

1. 半缺省参数必须从右往左(连续的)依次来给出左边的参数可以不指定。例如,int func(int a, int b = 5, int c = 10)是合法的,但int func(int a = 1, int b, int c)是不合法的。

2. 缺省参数只能在函数声明中指定,不能在函数定义中重新指定。这意味着如果在函数声明中指定了缺省参数,那么在函数定义中不能再次指定。

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

4. C语言不支持(编译器不支持)

5. 在调用函数时,可以省略缺省参数,此时函数会使用默认值。如果要指定某个参数的值,可以通过参数名指定,例如func(10, 20, 30)func(10, 20)


函数重载:

当遇到函数名相同的时候,c语言无法解决这个问题,而C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。

需要注意的是:c++的函数重载只有三种情况:

 1.参数类型不同:

int add(int a, int b);
int add(double a, double);

2.参数个数不同:

int add(int a, int b);
int add(int a, int b,int c,int d);

需要注意的是 

int add(int a = 5, int b = 1)
{
	return a + b;
}
int add(int a, int b, int c=5)
{
	return a + b + c;
}

这两个也是构成函数重载的,但是在两个函数同时存在时,并且调用时都只传两个函数是有问题的

 

对应的报错,没有对于重载函数进行报错,只是add调用分不清要调用哪一个; 

3. 参数类型顺序不同:

int add(int a, double b);
int add(double a, int b);

错误举例:

int add(int a, double b);
double add(int a, double b);

更详细了解:

c++基础梳理(四):C++中函数重载 - 知乎 (zhihu.com)icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/620328348


 引用

在c++中没有指针这一定义一说,但是c++实在c的基础上进行产生的,所以还是兼容c的,还是可以用c的指针。

但是在c++中也有引用的存在,引用就是相当于给他起了个外号

就比如张三在城里面别人叫他张三,在村里面别人都叫他二蛋,在家里面都被叫做二小,

这里的张三就可以被当为变量名,二蛋与二小,就是他的外号,也就是引用


引用的举例: 

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


 注意事项:

1.引用在定义是要进行初始化

int& a;错误

2.可对同一变量多次引用,但一个引用,只能对一个变量进行引用,不可以更改

所以引用还是很专一的;

引用做返回值 

int& add(int a, int b)
{
	int sum = a + b;
	return sum;
}
using namespace std;
int main()
{
	int ret = add(5, 6);
	return 0;
}

这里返回的是sum的“外号”

但是这个代码还是有点问题的,以后会专门出一个博客进行详细分析,

可以先看这个:如何理解引用作为函数的返回值?_引用返回值怎么理解-CSDN博客

 引用做参数:

int add(int& a, int& b)
{
	int sum = a + b;
	return sum;
}
using namespace std;
int main()
{
	int a = 5;
	int b = 6;
	int ret = add(a, b);
	return 0;
}

 两者的优点:

传引用参数:(任何时候都可以)

1.提高的效率

2.输出行参数(形参的修改,影响实参)

传引用返回:(出了函数作用域对现象还在就可以)

1.提高了效率

2.修改返回对象的数据

权限  

对于权限的讲解,是由权限放大与缩小来进行详细讲解。 

权限分为

1.权限平移

2.权限放大

3.权限缩小

 权限平移

权限平移也是正常的情况。 

	const int a = 5;
	const int& b = a;

 权限放大

#include<iostream>
int main()
{
	int a = 5;
	double& b = a;
	return 0;
}

	const int a = 5;
	int& b = a;

 其就会报错:

这是因为,变量a是被const 修饰过后,是不允许修改的,但是根据上面的理解,进行引用后,是允许通过对b进行修改,从而达到进行对a的修改,所以只看第二行来说,正常匹配来说,b也是不可以修改的,但是b是可以修改a的值,所有相对于a来说,b的权限是放大的。

权限缩小

	int a = 5;
	const int& b = a;

 权限的缩小是不会进行报错的。这一点很好理解,不详细解释;

同样来说a是可以修改,但b不可以修该,所以b的权限相对于正常匹配来说是缩小的。

特别注意,一定要理解

 我们先看一下这个代码,

#include<iostream>
int main()
{
	int a = 5;
	double& b = a;
	return 0;
}

发现编译不通过,这是为什么?

实际上,代码在运行时,会在中途开一个临时空间,存储临时变量

 

这里的tmp存的就是b,但是tmp时临时变量,他的特点就是具有常性,不可以进行修改,但是b与a不是同类型,需要进行整形提升来进行匹配a,但是这一步又在tmp处进行,所以就会编译不成功。 

但是有的地方会说这是权限放大,这又是为什么?

这是因为: 因为在这种情况下,变量b引用了变量a的内存地址,并且可以访问和修改a的值,即使b的类型是double而a的类型是int。这意味着通过b可以直接访问和修改a的值,这种行为可能会导致意外的结果或错误。因此,这种情况被称为权限放大,因为变量b获得了访问和修改变量a的权限。



内联函数:

内联函数的存在就是为了弥补宏的缺点,

宏的缺点就是:

1.容易出错,语法坑多并且复杂;

2.不可以调试,因为在预处理阶段,已经全部进行替换;

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

但是宏也是有优点的:

比如1.没有类型的严格限制;

2.针对频繁调用部分,减少了栈帧的浪费,提高了限制;

于是在c++祖师爷对于宏定义的各种不满下,便诞生了内联与模板,

内联函数是一种在编译时将函数体直接插入调用位置的优化技术,可以减少函数调用的开销,提高程序的执行效率。然而,过长的内联函数也会带来一些问题和危害,主要包括以下几点:

  1. 增加代码体积:内联函数会直接将函数体插入到调用位置,如果函数体过长,会导致代码体积增大,增加程序的内存占用和加载时间。

  2. 可读性下降:过长的内联函数会使代码变得冗长复杂,降低代码的可读性和可维护性,不利于代码的理解和调试。

  3. 编译时间增加:内联函数的展开是在编译时进行的,如果函数体过长,会增加编译时间,降低开发效率。

  4. 缓存失效:过长的内联函数会增加代码的复杂性,可能导致缓存失效,影响程序的性能。

因此,对于内联函数,应该根据实际情况进行合理的使用,避免函数体过长,保持代码的简洁性和可读性。在需要进行优化的情况下,可以考虑将部分函数进行内联优化,而不是将所有函数都进行内联处理。 

但是又有一点内联函数是不允许定义与声明分离的,所以相对于函数(我们可以把函数三部分放于三个文件),内联就只可以放在两个文件,一般是一个放在.c一个放在.h文件里

原因:(在一个文件中,如果只有声明,无法展开只可以连接时copy,但是内联函数不会进入符号表,不会进行查找)

之余种种原因,导致内联函数很强大,但是我们也要慎用内联函数,这里只举一个例子:

test.c文件 

int main()
{
	int a = 5;
	print(a);
	return 0;
}

test.h文件

#include<iostream>
using namespace std;

inline void print(int a)
{
	cout << a << endl;
}

 关键字auto

using namespace std;
int main()
{
	int a = 5;
	auto b = &a;//auto可以推算出b为 int* 类型
	auto& d = a;//auto可以推算出d是a的引用
	auto c = a;//auto可以推算出c为int 类型
	return 0;
}

这样的类型无法看出auto的方便之处,但是这样呢

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <unordered_set>

using namespace std;

int main() {
    std::map<std::string, std::vector<std::pair<std::string, std::unordered_set<int>>>> myMap;
    return 0;
}

哎呀,太长了,但如果用auto直接替代

auto myMap = map < string, vector < pair<string, unordered_set<int>>>>();

很方便吧!!!

然而auto的作用还不出如此,还涉及到迭代器

for(auto e:arr)

这里的arr就是需要跌代的数组名,这里的e就是依次将数组的值赋值给e

然后再自动跌代,自动结束 

#include <iostream>
using namespace std;
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
    for (auto e : arr)
    {
        cout << e << " ";
    }
    cout << endl;
    return 0;
}

#include <iostream>
using namespace std;
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
    for (auto& e : arr)
    {
        e++;
    }
    for (auto e : arr)
    {
        cout << e << " ";
    }
    cout << endl;
    return 0;
}

但是打印,还是优点需要注意的,比如这个代码:

#include <iostream>
using namespace std;
void print(int arr[])
{
    for (auto e : arr)
    {
        cout << e << " ";
    }
    cout << endl;
}
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
    print(arr);
    return 0;
}

这段代码是运行错误的,其原因就是函数内部的arr不是函数名;

空指针nullptr

在c语言中我们习惯用NULL来表示指针,但是在c++中 

然而空指针其实也用宏来实现的:

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

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

所以经过在c++11中便修改了空指针为nullptr

具体想了解的可以读nullptr | Microsoft Learn

  • 28
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dev-C++是一款流行的集成开发环境(IDE),用于C和C++编程。下面是Dev-C++入门教程: 1. 下载和安装:首先,你需要从Dev-C++官方网站下载并安装最新版本的Dev-C++。安装过程相对较简单,按照提示进行操作即可。 2. 创建新项目:打开Dev-C++后,点击菜单栏上的"File",然后选择"New"来创建一个新项目。在弹出的窗口中,选择"C++ Project"或"C Project",并为项目命名。 3. 编写代码:在项目中的源文件上右键点击并选择"Add new",然后选择"C++ Source"或"C Source"。在弹出的代码编辑器中,你可以编写C或C++代码。 4. 编译和运行:点击菜单栏上的"Execute",然后选择"Compile & Run"来编译和运行你的代码。如果一切顺利,你将在输出窗口中看到"Hello world"的输出。 注意:在编写代码时,你可以使用C++的输出流对象cout来输出文本。在Dev-C++的代码示例中,你会看到类似于"cout<<"Hello world";"这样的代码段。这是C++中一种常用的输出语法。 这就是Dev-C++入门教学。希望对你有所帮助!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Dev-c++入门教程1(模板及使用)](https://blog.csdn.net/zzz209/article/details/109955745)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值