IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 从C快速入门C++ 一.命名空间、引用、函数重载... -> 正文阅读

[C++知识库]从C快速入门C++ 一.命名空间、引用、函数重载...

?C++是一种计算机高级程序设计语言,由C语言扩展升级而产生 ,最早于1979年由本贾尼·斯特劳斯特卢普在AT&T贝尔工作室研发。 C++既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。C++擅长面向对象程序设计的同时,还可以进行基于过程的程序设计。在这里插入图片描述

C++关键字

C++98 中有63个关键字, C90(C89) 32个关键字
1111111

    C++63个关键字(有红色波浪线为C语言关键字)

可见 C++ 关键字是在 C语言基础上增加了许多。

?
?
?

命名空间

在学习命名空间之前还需要了解一些关于 C++ 的知识
?

C++预处理器 和 iostream 文件

C++ 和 C一样都使用一个预处理器,在程序进行主编译之前对源文件进行处理

在 C 语言中我们都知道将 C源代码 变成 可执行文件要经过 :
在这里插入图片描述
C++ 仍使用 #include 编译指令 使预处理器将 iostream 文件的内容添加到程序中以完成 io (输入输出)等,所以使用 cin 输入 和 cout 输出都需要包含文件 iostream

?

头文件名

C++ 也使用 编译器自带的头文件(包含文件),相较于 C语言中 如熟悉的 stdio.h (必须使用扩展名 h), C++头文件没有扩展名,有些杯=被重新命名 去掉后缀 h 加上前缀 c 如 cstdlib,不过C++ 仍可以使用老式的 C 的头文件 (详见下图)
在这里插入图片描述

命名空间定义

在C/C++中,变量、函数和类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字 污染,namespace关键字的出现就是针对这种问题的

? 简而言之,在使用两个代码量较大的项目时 可能存在两个名称都为 fun() 的函数 或者 a 变量, 编译器无法分辨。而命名空间的存在就可以使工程代码封装在 namespace 中, 通过命名空间的名称来明确想使用哪个方法或变量。

举个例子:张三是北大的学生,而李四是清华的学生,他俩的学号都是 001 ,如果你只知道学号无法确定到底是谁,但是如果告诉你是清华的 001 号你就知道指的是 李四。

namespace QingHua
{
	struct student{
		char name[5];
		int num;
	};
	struct student s = { "LiSi", 001 };
}

注:定义一个命名空间相当于定义一个的

命名空间使用

● 加命名空间名称及作用域限定符( :: )

当用户只想使用命名空间中某个成员时使用这种方式 ? 推荐

std :: cout << "Hello C++";

● 使用 using 将命名空间成员引入

当用户需要频繁使用某个成员时使用,相当于全局变量

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

● 使用 using namespace 将命名空间成员引入

当需要使用命名空间许多成员而不想每次使用作用于限定符时,直接将命名空间所有成员引入,这是一种省事的方法但是当在大型项目可能会导致命名冲突潜在问题

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

?

函数重载

默认参数

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

?可以形象的认为是参数中的 “备胎”。

全缺省参数(参数都有默认值)

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

半缺省参数(部分参数有默认值)

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

注:对于带参数列表的函数必须从右往左添加默认值,不能跳着给参数初值void fun(int a = 0,int b, int c = 1) //error
在生命和定义中只能添加一次默认值, 否则会报错:重定义
?

函数重载定义

默认参数能够让你使用不同数目的参数调用同一个函数,而函数重载能让你使用多个同名函数。(函数的多态)

C++允许在同一作用域中出现同名但是 参数列表不同的几个函数,常用来处理功能类似但数据类型不同的问题。

重载就类似于汉语中一词多义的那种感觉。

为什么C语言不支持重载?
简单来说,因为 C 语言和 C++ 对于函数名修饰规则不一样, C++ 的编译器会对函数名称进行修饰,它会根据函数中的形参类型对每个函数名进行修饰,使编译器和链接器能够区分同名不同参的函数。

linux 下的函数名修饰测试
在这里插入图片描述
在这里插入图片描述

在《程序员的自我修养中》 对 gcc , g++ 与 window vs 的函数名修饰规则做了解释
在这里插入图片描述
在这里插入图片描述

函数重载调用原理

?在函数编译阶段编译器会对函数参数类型进行推演
1> 如果找到参数类型匹配的函数则直接调用
2> 如果没有找到 编译器会尝试进行隐式类型转换如果又可以调用的函数就调用,否则就会报错

?

?

?

引用

引用是已定义变量的别名(另一个名称)。主要用于做函数的形参。

引用的特性
? 1. & 不是取地址运算符,而是类型标识符(就像 char*中的 *)。
? 2. 必须在声明引用变量的时进行初始化
? 3. 一个变量可以有多个引用(别名),但一旦引用一个实体就不能引用其他实体。
? 4. 引用相当于 const 指针,可以理解为 int & b = a; 相当于int* const p = &a (即Tpye & == T * const)

int a = 10;
int& b = a;  
//int& b;   
//b = a;    //error!

.
下面有两个有意思的代码

void test()
{
	const int a = 10;
	//int& ra = a;     //编译出错,类型不匹配 a 为常量
	//int& rb = 10;   //编译出错,原因同上
	double num = 12.34;
	// int& rd = num   //编译出错
	const int& rd = num;
	num = 100;
}

当用 int& 引用 double 变量 b 时直接会报错,但将加上 const 后只有如下的 warning
在这里插入图片描述
在这里插入图片描述

为什么在好像引用成功 num 后,改变num 值后 num 的引用确仍然是 12 ???

结论:num的 “引用” rd的地址与num并不相同,其实rd所引用的并不num而是存储着num的整数部分的临时空间。
临时空间是编译器创建的,用户即不知道该块空间的名字,也不知道该块空间的地址,因此用户是无法修改临时空间中内容的,既然不能修改认为临时空间具有常性。所以加上const编译才通过。

2.在这里插入图片描述
这里 ret 引用的是 add(10,20)的结果 理应是30,为什么ret值为4呢??

在这里插入图片描述
函数调用开辟栈帧,来保存局部变量,函数运行结束开辟的栈空间回收(但是只是接触函数和栈空间的使用关系,但数据不会被清空)。如,酒店退房只是回收房卡无法入住,不会拆掉房间。

注: 所以函数返回时,如果返回对象没被系统回收,就可以用引用返回,否则必须使用传值返回。不能返回函数栈上的空间否则就会出现如上的问题。

?

传值 引用效率比较

struct A
{
	int a[100000];
};

void TestFunc1(A a){}
void TestFunc2(const A& a){}
void TestFunc3(A* a){}

void Test()
{
	A a;
	// 以值作为函数参数
	size_t begin1 = clock();
	for (size_t i = 0; i < 100000; ++i)
		TestFunc1(a);
	size_t end1 = clock();

	// 以引用作为函数参数
	size_t begin2 = clock();
	for (size_t i = 0; i < 100000; ++i)
		TestFunc2(a);
	size_t end2 = clock();

	// 以地址作为函数参数
	size_t begin3 = clock();
	for (size_t i = 0; i < 100000; ++i)
		TestFunc3(&a);
	size_t end3 = clock();

	// 分别计算两个函数运行结束后的时间
	cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;    //传值传参
	cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;    //传引用传参
	cout << "TestFunc2(A*)-time:" << end3 - begin3 << endl;    //传地址传参
}

在这里插入图片描述
结论:引用做参数和传地址效率差不多,而传值因为要发生拷贝效率很低,这也是传引用做参数的优点。

?

?

引用和指针的区别

学过C语言的人都听过指针,或亲身体验过其复杂但又巧妙的设计

在语法层面引用是一个别名,和其引用实体公用同一块空间;而指针(变量)是存放地址的一个变量。 真的这么简单吗?所以C++是如何实现引用的呢??

在这里插入图片描述

通过查看汇编指令我们惊奇的发现,不能说指针和引用是毫无关系…这简直一毛一样啊! 原来 C++ 的引用也只不过是指针披上了引用的外衣罢了,底层实现逻辑仍是指针的方式。

结论
● 引用语法层面为了便于理解,而底层引用是按照指针方式实现的

引用指针语法层面不同点(概念,特性)
(1) 引用是一个变量的别名,而指针(变量)存放变量的地址。
(2) 引用在定义时必须要初始化,不能先声明再赋值,而指针可以。
(3) sizeof()含义不同:sizeof 引用结果是引用类型的大小,而 siezof 指针始终是地址大小(32位下 4字节,64位下8字节)
(4) 访问方式不同: 指针需要解引用, 引用不需要。
(5) 引用自增 +1 是所引用的变量加一, 而指针 +1 是加上指针所指向类型的大小
(6) 有多级指针(二级指针),没有多级引用。
(7) 没有 NULL 引用, 有 NULL 指针。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-17 21:52:22  更:2022-03-17 21:53:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:36:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码