c++中和c语言不相同的地方

2023-11-02

       c++糅合了c语言的语法,并且在c语言的基础上进行了改进,并且具有向下兼容的特性;

        但是c++改进了什么东西呢?今天就来学习一下吧;

目录

命名空间 (namespace)

cout与cin与endl

流插入符与流运算符

using namespace (命名空间名)的缺陷

命名空间的嵌套和合并

引用

常引用

做返回值

引用做返回值的好处

引用和指针的对比

重载函数

 缺省函数

内联函数

内联函数的特点

关键字auto

范围for循环

c++的nullptr

总结


命名空间 (namespace)

 在使用c语言写代码的时候,我们有时候会碰到这种报错:

有时候是因为代码过长,忘记自己已经定义了这个变量,有时候兴许是某处的域没注意到;

就会出现这种状况;

而c++针对这种情况推出了一个新的语法——命名空间; 

语法:

namespace (命名空间名)

{

        (变量表)
}

 使用方法:

(命名空间名)::  (变量名);

or

using namespace  (命名空间名);

我们看看实例:

#include<iostream>

namespace Date {
	int year = 2022;
	int month = 9;
	int date = 28;
}

int main()
{
	int date = 10;
	printf("%d\n%d", Date::date, date);
	return 0;
}

 我们可以看到,编译器没有报错,并且成功的输出了结果;

而c++中我们用的最多的命名空间就是std了

那么std又是什么命名空间呢?

这里我们就不得不提一下c++专用的输入输出语句了;

cout与cin与endl

c++中,更新了新的输入输出方式:cout与cin;

其使用方式是:

int a ;

std::cin>>a;

std::cout<<a<<std::endl;//std::endl其实和'\n'的作用是一样的;

正如上面所写,所谓cin和cout实际上也是在一个命名空间中有的,大家可能很疑惑,cout和cin按理说应该是函数一类,为何会在命名空间中呢?

实际上命名空间中不仅可以设置变量,你还可以设定函数,结构体等一系列东西;

那么这两个输入输出语句有什么特别之处,能够胜过scanf和printf呢?

这就不得不聊到c++中新添加的几个运算符了

流插入符与流运算符

流插入运算符:>>

流提取运算符:  >>

在c语言中提到的流只有在文件中用到过,比如 fgetc 或者 fgets 是从文件流中提取字符或者字符串;

而c++则可以利用cin和cout直接提取流用来输入或者输出,并且会自动辨别变量的类型

 可以自动辨别!这可是一个好东西啊,以后要多用,当然也有人觉得 std:: 这个前缀很麻烦,我们可以在使用 cin 和 cout 之前写下 "using namespace std;"就可以了;

提到了using namespace std;之后,就不得不提到命名空间这个用法的缺陷了;

using namespace (命名空间名)的缺陷

之前提到过,命名空间的最大的好处是可以避免重命名的错误,但是当我们使用这条语句后,这个好处就没有了;

就好像原本紧闭的大门被开了一个洞,大家都能随便进出了;

因此是否使用这条语句,还得看实际场景;

当然,这个缺陷c++的创始人当然也发现了,于是他有一个好点子——局部展开;
 

语法:

using namespace  (命名空间名):: (空间内部变量);

这样大部分都能避免重定义,并且可以指展开常用的;

命名空间的嵌套和合并

命名空间虽然内部的变量不能直接使用,但是其实内部变量全部都是全局变量;

只是因为namespace限定了这些变量的访问方式;

因此,命名空间又有一个骚操作——合并

 命名空间的合并只有一个条件——空间名相同;

就像这样:

#include<iostream>

using namespace std;

namespace Date {
	int year = 2022;
	
}
namespace Date {
	int month = 9;
	int date = 28;
}
int main()
{
	int date = 10;
	printf("%d\n%d", date, Date::date);
	return 0;
}

 就像这样;

而命名空间既然只是将域限定了,那么命名空间内部能不能再限定一个域呢?

答案是肯定的,这就是命名空间的第二个骚操作之——嵌套;

namespace Date
{
	int year = 2022;
	int month = 9;
	int day = 28;
	namespace Week {
		int  Mon = 1;
		int Tue = 2;
		
	}
}

int main()
{
	cout << Date::Week::Mon << endl;

	return 0;
}

 实际上这个嵌套不过是在命名空间内再搞一个命名空间罢了,大家了解一下就可以了;

引用

在c语言中,我们如果需要用函数将两个变量的值交换的时候,我们需要用到指针才能将数据成功交换;

但是指针比较难,因此c++对此进行了改进,那就是引用;

什么是引用?

实际上就是相当于给变量起了一个别名;

int main()
{
	int  a = 10;
	int& ra = a;
	ra = 0;
	cout << ra << endl;

	return 0;
}

 我们可以看到,变量 a 的值确实改变了,这就是引用的作用;

有的同学就会问了,这有什么,我们指针也能改变 a 的值啊,有什么用啊?

虽然这里表现上看上去和指针类似,实则大不相同;

我们的指针其实也是一种变量,只是这个变量里面存的是另一个变量的地址,而指针依旧占用内存;

而引用则不同,引用实际上就是相当于给变量起了一个别名,实际上并没有占用内存;

既然知道了引用和指针的区别,我们就来继续了解一下引用的规则;

1:引用必须一开始就初始化;

2:一个变量可以有多个引用;

3:引用初始化一个实体后,就不能引用别的实体;

了解后,我们再来了解引用的一些奇奇怪怪的错误;

常引用

 如图上所示,我们设了一个常变量a,并且用 ra  引用 a,却显示错误;

这就涉及了权限的放大和缩小了;

我们这张图就是典型的权限放大;

const int a 是一个常变量,只可读,不可写;

而 ra 则是一个变量,可读,可写;

这就涉及到了权限放大,而权限只能缩小不能放大;

但是如果我们反过来

这样就可以了;

按照上面的说法,ra只可读,不可写,而a可读可写,因此是权限缩小,可以使用; 

 当然,若是两边权限相同当然是可以的

 两边都只可读不可写,权限的平移,因此可以;

做返回值

当用引用返回的时候,有一个需要注意的地方,那就是那个引用的实体地址不在栈区;

又或者说,引用的实体的地址没有被销毁;

 就像这样,途中a的值已经修改成a了,但是输出依旧是0;

这是因为返回的n的空间已经被销毁了,可以随意访问,那么自然a的值就会被随机改变了;

因此我们需要给n加个修饰符;

 这样就没出错了;

引用做返回值的好处

对比:

struct A { int a[10000]; };
A a;
// 值返回
A TestFunc1() { return a; }
// 引用返回
A& TestFunc2() { return a; }

void TestReturnByRefOrValue()
{
	// 以值作为函数的返回值类型
	size_t begin1 = clock();
	for (size_t i = 0; i < 100000; ++i)
		TestFunc1();
	size_t end1 = clock();
	// 以引用作为函数的返回值类型
	size_t begin2 = clock();
	for (size_t i = 0; i < 100000; ++i)
		TestFunc2();
	size_t end2 = clock();
	// 计算两个函数运算完成之后的时间
	cout << "TestFunc1 time:" << end1 - begin1 << endl;
	cout << "TestFunc2 time:" << end2 - begin2 << endl;
}

int main()
{
	TestReturnByRefOrValue();
	return 0;
}

 我们发现,引用做返回值的时候,其实还是很好用的,对性能消耗是非常小的;

引用和指针的对比

1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
2. 引用 在定义时 必须初始化 ,指针没有要求
3. 引用 在初始化时引用一个实体后,就 不能再引用其他实体 ,而指针可以在任何时候指向任何 一个同类型实体
4. 没有 NULL 引用 ,但有 NULL 指针
5. sizeof 中含义不同 引用 结果为 引用类型的大小 ,但 指针 始终是 地址空间所占字节个数
7. 有多级指针,但是没有多级引用
8. 访问实体方式不同, 指针需要显式解引用,引用编译器自己处理
9. 引用比指针使用起来相对更安全

别看引用和指针有这么多不同,其实引用和指针在底层设计都是类似的;

 当我们转到反汇编看汇编代码的时候,我们发现,这两个在底层逻辑是一样的;

重载函数

在c语言中,不能够有相同名字的函数,但是在c++中,有一个新的概念名叫函数的重载;

可以使得我们的函数可以名字相同而不报错;

我们可以看看

 我们可以看到确实是运行了起来,那么为什么呢?

我们知道,代码需要经过 预编译——编译——汇编——链接几个阶段才能生成可执行文件;

而c++正是在这之中动了手脚;

它在编译的时候,会根据函数名称,形参个数,形参类型以及不同环境下的名字修饰规则,生成不同的函数名,随后编译器链接的时候,就会到对应的地址使用对应的函数了;

因此就能够实现函数重载;

函数重载规则

1.函数形参个数要不同;

2.函数形参类型要不同;

3.函数形参顺序要不同;

 缺省函数

c++中,我们的函数可以不给值,而在函数中直接给值;

就像这样;

缺省函数又分为全缺省和半缺省;

上图就是全缺省,即所有参数都有值;

接下来就是半缺省;

 半缺省就是有的值有初始值,有的没有;

那么缺省函数有什么需要注意的呢?

那是当然有的;

1. 半缺省参数必须 从右往左依次 来给出,不能间隔着给
2. 缺省参数不能在函数声明和定义中同时出现(若是两边缺省值不同会错误)
3. 缺省值必须是全局变量或者常量

只有注意了以上几点,才能够正确的使用缺省函数,还请注意;

内联函数

在讲这个之前,请大家回忆一下,大家还记得宏函数是什么吗?

宏函数在使用的时候,编译器会直接将函数内部的代码直接替换掉宏所在位置;

没有栈帧的消耗;

而内联函数也是类似的;

用inline修饰的函数,会在函数调用的位置展开,没有栈帧消耗,提升程序运行效率

接下来我们直接看看内联函数是怎么用的吧;

 那么内联函数和普通的函数有什么不同呢?

这就要去看看底层代码了;

 我们先看看普通函数的底层代码,发现Add前面有一个call指令,也就是调用Add函数的指令;

我们再来看看内联函数的底层代码;

我们发现,此处并没有call指令,而是直接利用 eax寄存器将数据放到函数内部;

这就是内联函数的作用;

内联函数的特点

1.内联函数是一种以空间换时间的做法,虽然会增大程序的大小,但是会减少程序运行时间;

2.内联对编译器只是一个建议,不同编译器的要求不同,一般建议是函数体较小,不用递归且使用频繁的函数才使用内联

3.内联函数的声明和定义不能分离,若是分离函数的链接可能会出错,因为inline函数被展开了,没有函数地址,链接时会出错

之前用宏来引入内联函数,那么内联函数和宏有什么不同呢?

 宏:

优点:

1.增加代码复用性

2.增加效率

缺点:

1.没有类型安全检查;

2.代码可读性差;

3.容易出错;

4.不可调试

内联函数:

优点:

1.增加代码复用性;

2.增加效率;

3.有类型安全检查; 

4.可读性好;

5.可以调试;

缺点:

1.不可递归;

2.声明和定义不可分离

不过有一点需要注意,内联函数其实只是一个建议,并不代表编译器一定会执行;

比如有的编译器,你的代码超过20行或者30行,inline关键字就会被忽略。

关键字auto

在c++中还有这样一个关键字:auto;

那么auto是干什么的呢?

用于将那些类型名特别长容易写错的类型推导出来;

auto是一个类型指示器来指示编译器,并且 auto 声明的变量必须在编译时期推导出来;

 那么auto怎么用呢?

int a;

auto b = a;

auto c = 'a';

这样,就声明了int类型的b变量,char类型的c变量;

 但是auto虽然好用,但是也有很多限制;

auto的限制:

1.auto定义变量必须初始化;

2.auto不能作为函数的参数;

3.auto不可直接声明数组;

4.auto用来引用别的变量时,必须写auto&,而auto指针则没必要加*;

5.在一行定义多个auto变量,必须类型的都一样;

 实例

int main()
{
	int  a = 10;
	auto b = a, c = 10;
	auto& ra = a;
	auto d = &a;
	auto* e = &a;
	return 0;
}

这样就是auto的使用方法了;

范围for循环

c++中有一个范围的or循环,可以直接来循环遍历数组内部的所有元素;

使用方法:

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

int main()
{
    TestFor();
    return 0;
}

  我们可以看到,我们不仅可以访问内部的数据,也可以改变内部的数据;

c++的nullptr

在c++中,NULL并不是所谓的空指针;

实际上c++中的NULL是数据0;

nullptr才是空指针;

这点需要注意;

总结

        c++针对C语言的一些缺陷或者说不好用的地方都提出了新的语法,比如难以理解的引用,以及函数重载等技术,都说明C++是C语言的升级,而且C++语言包含C语言的语法,可以直接使用C语言的语法,这点需要点个赞。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++中和c语言不相同的地方 的相关文章

  • InvalidOperationException - 对象当前正在其他地方使用 - 红十字

    我有一个 C 桌面应用程序 其中我连续创建的一个线程从源 实际上是一台数码相机 获取图像并将其放在 GUI 中的面板 panel Image img 上 这必须是另一个线程 如它是控件的代码隐藏 该应用程序可以工作 但在某些机器上 我会在随
  • 用于代数简化和求解的 C# 库 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 网络上有很多代数求解器和简化器 例如 algebra com 上不错的代数求解器和简化器 然而 我正在
  • 注销租约抛出 InvalidOperationException

    我有一个使用插件的应用程序 我在另一个应用程序域中加载插件 我使用 RemoteHandle 类http www pocketsilicon com post Things That Make My Life Hell Part 1 App
  • 如何在 .NET Framework 2.0 中模拟“Func<(Of <(TResult>)>) 委托”?

    我尝试使用这个类代码项目文章 http www codeproject com KB threads AsyncVar aspx在 VB NET 和 NET Framework 2 0 中 除了这一行之外 所有内容似乎都可以编译Privat
  • Directory.Delete 之后 Directory.Exists 有时返回 true ?

    我有非常奇怪的行为 我有 Directory Delete tempFolder true if Directory Exists tempFolder 有时 Directory Exists 返回 true 为什么 可能是资源管理器打开了
  • 提交后禁用按钮

    当用户提交付款表单并且发布表单的代码导致 Firefox 中出现重复发布时 我试图禁用按钮 去掉代码就不会出现这个问题 在firefox以外的任何浏览器中也不会出现这个问题 知道如何防止双重帖子吗 System Text StringBui
  • 在 LINQ 中按 Id 连接多表和分组

    我想按categoryId显示列表产品的名称组 这是我的代码 我想要我的视图显示结果 Desktop PC HP Red PC Dell Yellow PC Asus Red SmartPhone Lumia 720 Blue 我的组模型
  • 为什么极端下派生类(多重虚拟继承)的大小包括超类成员大小的两倍?

    include
  • 获取两个工作日之间的天数差异

    这听起来很简单 但我不明白其中的意义 那么获取两次之间的天数的最简单方法是什么DayOfWeeks当第一个是起点时 如果下一个工作日较早 则应考虑在下周 The DayOfWeek 枚举 http 20 20 5B1 5D 3a 20htt
  • java.io.Serialized 在 C/C++ 中的等价物是什么?

    C C 的等价物是什么java io Serialized https docs oracle com javase 7 docs api java io Serializable html 有对序列化库的引用 用 C 序列化数据结构 ht
  • 如何使用 LINQ2SQL 连接两个不同上下文的表?

    我的应用程序中有 2 个数据上下文 不同的数据库 并且需要能够通过上下文 B 中的表的右连接来查询上下文 A 中的表 我该如何在 LINQ2SQL 中执行此操作 Why 我们正在使用 SaaS 产品来跟踪我们的时间 项目等 并希望向该产品发
  • DbContext 和 ObjectContext 有什么区别

    From MSDN 表示工作单元和存储库模式的组合 使您能够查询数据库并将更改分组在一起 然后将这些更改作为一个单元写回存储 DbContext在概念上类似于ObjectContext 我虽然DbContext只处理与数据库的连接以及针对数
  • 如何检测表单的任何控件的变化?

    如何检测 C 中表单的任何控件的更改 由于我在一个表单上有许多控件 并且如果表单中的任何控件值发生更改 我需要禁用按钮 我正在寻找一些内置函数 事件处理程序 属性 并且不想为此创建自定义函数 不 我不知道任何时候都会触发任何事件any控制表
  • 为什么 std::strstream 被弃用?

    我最近发现std strstream已被弃用 取而代之的是std stringstream 我已经有一段时间没有使用它了 但它做了我当时需要做的事情 所以很惊讶听到它的弃用 我的问题是为什么做出这个决定 有什么好处std stringstr
  • “接口”类似于 boost::bind 的语义

    我希望能够将 Java 的接口语义与 C 结合起来 起初 我用过boost signal为给定事件回调显式注册的成员函数 这非常有效 但后来我发现一些函数回调池是相关的 因此将它们抽象出来并立即注册所有实例的相关回调是有意义的 但我了解到的
  • 动态添加 ASP.Net 控件

    我有一个存储过程 它根据数据库中存储的记录数返回多行 现在我想有一种方法来创建 div 带有包含该行值的控件的标记 如果从数据库返回 10 行 则 10 div 必须创建标签 我有下面的代码来从数据库中获取结果 但我不知道如何从这里继续 S
  • 使用 C# 读取 Soap 消息

  • 按 Esc 按键关闭 Ajax Modal 弹出窗口

    我已经使用 Ajax 显示了一个面板弹出窗口 我要做的是当用户按 Esc 键时关闭该窗口 这可能吗 如果有人知道这一点或以前做过这一点 请帮助我 Thanks 通过以下链接 您可以通过按退出按钮轻松关闭窗口 http www codepro
  • 调用堆栈中的“外部代码”是什么意思?

    我在 Visual Studio 中调用一个方法 并尝试通过检查调用堆栈来调试它 其中一些行标记为 外部代码 这到底是什么意思 方法来自 dll已被处决 外部代码 意味着该dll没有可用的调试信息 你能做的就是在Call Stack窗口中单
  • 如何部署“SQL Server Express + EF”应用程序

    这是我第一次部署使用 SQL Server Express 数据库的应用程序 我首先使用实体 框架模型来联系数据库 我使用 Install Shield 创建了一个安装向导来安装应用程序 这些是我在目标计算机中安装应用程序所执行的步骤 安装

随机推荐

  • Java 的VO、DTO、TO、BO等概念总结

    当涉及到Java中的数据传输和对象封装时 有几个常见的概念 它们在不同的上下文中具有不同的用途 以下是这些概念的总结 VO Value Object 含义 VO表示值对象 用于封装一组相关的数据字段 通常没有业务逻辑 用途 VO通常用于数据
  • PBFT共识算法原理

    1 容错类型 PBFT假定错误可以是拜占庭类型的 也就是说可以使任意类型的错误 比如节点作恶 说谎等 这有别于crash down类型的错误 raft paxos这类共识算法只能允许crash down类型错误 节点只能crash而不能产生
  • 推荐三款适合运维小白的网络监测工具

    对于刚刚步入职场的运维小白而言 面对工作中的突发情况时常会感到手忙脚乱 为了帮助他们更好地应对这些挑战 本文将介绍三款特别适合运维新手使用的网络监测工具 1 Zabbix是一个功能强大的网络监控系统 可以监视各种网络设备的性能指标 应用的运
  • Python图形界面设计 Tkinter GUI编程组件的使用

    一 学习目标 1 GUI库 2 Tkinter库 3 导入Tkinter库 4 4 Tkinter窗口中显示中文 5 Tkinter 组件 二 重点知识 1 GUI库 GU1 Graphical User Interface 图形用户界面
  • 【Python数据挖掘课程】二.Kmeans聚类数据分析及Anaconda介绍

    这次课程主要讲述一个关于Kmeans聚类的数据分析案例 通过这个案例让同学们简单了解大数据分析的基本流程 以及使用Python实现相关的聚类分析 主要内容包括 1 Anaconda软件的安装过程及简单配置 2 聚类及Kmeans算法介绍 3
  • 使用SoapHeader实现Soap请求验证

    http www laruence com 2010 03 26 1365 html PHP的Soap Extension中 对于SoapServer来说 并没有方法可用得到 处理客户端发送的SoapHeader信息 网上也有很多人认为 只
  • CSS&JavaScript讲解

    CSS 概念 全称 Cascading Style Sheets 层叠样式表 用于美化页面 布局页面 层叠 多个样式可以作用在同一个html的元素上 同时生效 好处 功能强大 将内容展示和样式控制分离 降低耦合度 解耦 让分工写作更容易 提
  • QQ分享失败原因

    通过qq分享链接到QQ空间 QQ当中 分享失败 要么就是调起qq后调不起分享框 排查了很久才找到原因 原来是分享的url链接不正确
  • PAT-B 1032 挖掘机技术哪家强 (20分)

    为了用事实说明挖掘机技术到底哪家强 PAT 组织了一场挖掘机技能大赛 现请你根据比赛结果统计出技术最强的那个学校 输入格式 输入在第 1 行给出不超过 10 5 的正整数 N 即参赛人数 随后 N 行 每行给出一位参赛者的信息和成绩 包括其
  • leetcode3 链表相加

    package 剑指offer 我们要明白链表逆序的好处 4 gt 2 gt 5 5 gt 8 gt 1 9 gt 0 gt 7 第一 数需要对齐 尤其是两个数不是相同位数的情况 那么那就回想一下 我们做加法都是尾部对齐 而不是头部 这样的
  • 如何在pycharm使用Anaconda下载的库

    如何在pycharm使用Anaconda下载的库 这篇文章 介绍了如何在pycharm项目 project 里建立Anaconda环境 从而引用anaconda下载的库 site packages 但我个人使用后发现 换了虚拟环境后无法实现
  • 旋转的矩阵-c++

    旋转的矩阵 数据结构 题目描述 给定一个n m的矩阵 请以顺 逆时针交替旋转的方式打印出每个元素 Input Format 第一行n m 0
  • Error getting generated key or setting result to parameter object. Cause: org.apache.ibatis.executor

    报错信息 Error getting generated key or setting result to parameter object Cause org apache ibatis executor ExecutorExceptio
  • 毕业设计课题大全

    Java毕业设计课题大全 https blog csdn net My IT Road article details 90341793 软件工程毕业设计集合 https blog csdn net linzhiqiang0316 arti
  • tutk云平台服务器_哪家云服务器便宜?各家云平台活动详解【持续更新】

    不知不觉 双十一已经近在眼前 作为一年一度的购物狂欢节 无论对于商家还是消费者来说 都是一次畅快购物的饕餮盛宴 对于云平台来说 自然不会错过一年中绝佳的营销机会 各种优惠活动也是纷至沓来 在讨论哪家云服务器便宜之前 我们先来看看该如何选择云
  • 微信登录总结公众号登录小程序登录企业微信登录

    微信公众号 服务号登录 微信内部网页授权 第一步 请求CODE https open weixin qq com connect oauth2 authorize appid APPID redirect uri REDIRECT URI
  • VC6.0打开文件以及向工程中添加文件时程序崩溃自动退出

    换了一台电脑 vc6 0程序中 点击打开文件以及向工程中添加文件时 程序竟然崩溃自动退出了 不知什么原因 安装相同的vc程序 本本竟然出现此缘故 但是这个操作又是自己经常用到的 所以不得不解决 与上一台电脑不同的是 此电脑是win7系统 而
  • 最小二乘拟合平面——拉格朗日乘子法

    目录 一 算法原理 二 代码实现 1 python 2 matlab 三 算法效果 一 算法原理 设拟合出的平面方程为 a x b
  • tinyhttp

    博客园 http www cnblogs com letlifestop Tinyhttpd 是J David Blackstone在1999年写的一个不到 500 行的超轻量型 Http Server 用来学习非常不错 可以帮助我们真正理
  • c++中和c语言不相同的地方

    c 糅合了c语言的语法 并且在c语言的基础上进行了改进 并且具有向下兼容的特性 但是c 改进了什么东西呢 今天就来学习一下吧 目录 命名空间 namespace cout与cin与endl 流插入符与流运算符 using namespace