wordpress开发视频网站模板,建设网银登录官网,哪个公司网站建设好,京东优惠券网站建设目录
一.C的第一个程序
二.命名空间
1.namespace的价值
2.命名空间的定义
3.命名空间使用
三.C的输入与输出
1.iostream
2.流
3.std(standard)
四.缺省参数
1.缺省参数的定义 2.全缺省/半缺省
3.声明与定义
五.函数重载
1.参数个数不同
2.参数类型不…目录
一.C的第一个程序
二.命名空间
1.namespace的价值
2.命名空间的定义
3.命名空间使用
三.C的输入与输出
1.iostream
2.流
3.std(standard)
四.缺省参数
1.缺省参数的定义 2.全缺省/半缺省
3.声明与定义
五.函数重载
1.参数个数不同
2.参数类型不同
3.参数类型顺序不同
函数返回值不同是否能作为重载条件
带有缺省参数的函数能构成重载吗
六.引用
1.引用的概念和定义
2.引用的特性
2.1引用在定义是必须初始化
2.2一个变量可以有多个引用
2.3引用一旦引用一个实体再不能引用其他实体
3.引用的使用
3.1引用传参
3.2引用作返回值
4.const引用
5.指针和引用的关系
七.inline 1.inline的定义与概念
2.inline的特性
3.inline与宏函数的比较
八.nullptr
九.总结 一.C的第一个程序 第一个程序当然是“Hello World”不过这里我们使用C的语法进行实现。 在实现前我们创建的文件必须得是.cpp文件编译器在识别后缀为.cpp后才会调用C编译器这里后缀改为.c文件是会报错的。
#includeiostream
using namespace std;int main()
{cout Hello World endl;return 0;
}
运行结果 这里对于代码有疑问是正常的接下来我们来逐一讲解。
二.命名空间
1.namespace的价值 在C语言中如果一个声明的变量名刚好与其他变量名重复或者与函数名等重复则会出现报错例如下面这段代码
#includestdio.h
#includestdlib.hint rand 0;int main()
{printf(%d\n, rand);return 0;
}
报错片段 可以看到报错语句为重定义以前的定义是函数。 在这里我们期望rand是int类型但rand是函数类型这说明由于stdlib.h中rand()的存在编译器将rand识别为了函数在C语言中如果要解决这样的问题只能再取一个其他变量名但在C中我们可以用命名空间去解决命名冲突的问题。
2.命名空间的定义 定义命名空间需要用到关键字namespace后面跟命名空间的名字这里用mySpace举例再跟一对大括号{}{}中可以定义命名空间的成员成员可以是变量/函数/类型等。
代码演示
namespace mySpace
{int rand 0;int Add(int left, int right){return left right;}struct Node{struct Node* next;int val;};
} namespace本质是定义一个域在C语言中由于不用域中可以定义同名变量namespace也类似与这种特性namespace定义的域与全局域各自独立其通过域隔离解决了同名冲突的问题且命名空间不会影响变量的生命周期。 命名空间只能定义在全局同时namespace也可以嵌套定义。
代码演示
namespace mySpace
{namespace s1{int rand 0;int a 1;}namespace s2{int rand 10;int a 11;}
} printf(%d\n, mySpace::s1::a);printf(%d\n, mySpace::s2::a); 在调用的过程中我们使用域作用限制符::它能在编译时通过指定域的形式进行查找。 如第一条printf语句就是访问MySpace中命名空间s1中的整型变量a打印值为1。
运行结果 · 在项目目工程文件中同名的namespace会认为是一个namespace不会冲突 · 我们再定义一个头文件并创建一个同名namespace。 在包含头文件后可以看到程序并未报错并成功输出b的值这说明编译器认为两个namespace并不冲突为同一个命名空间。
3.命名空间使用 编译器的查找规则为 1.先局部再全局 2.指定域中查找 所以如果直接查找命名空间中的变量名而并未指定则会报错参考下面程序 如果要正确使用命名空间中定义的变量/函数有三种方式 1.运用域作用限制符指定命名空间访问项目中推荐使用。 2.使用using将命名空间中某个频繁使用的变量/函数展开项目中不推荐使用。 这样就可以让上面的程序不报错了但由于将命名空间中的a展开可能会有同名冲突的风险。 3.用using展开命名空间中的所有成员 项目中不推荐冲突风险大日常练习时方便推荐使用。 三.C的输入与输出
1.iostream C中的输入与输出不再使用stdio.h而是用iostreamiostream是Input Output Stream 的缩写库中定义了标准的标准的输入输出对象其中包含iostream也会间接包含stdio.h所以也能使用printf和scanf不同编译器可能会报错。
2.流 std::cin 是 istream 类的对象它主要面向窄字符narrow characters (of type char)的标准输入流。 std::cout 是 ostream 类的对象它主要面向窄字符的标准输出流。 std::endl 是⼀个函数流插入输出时相当于插入一个换行字符加刷新缓冲区。现在可以简单理解为换行符。 是流插入运算符是流提取运算符。C语言中用这两个运算符做位运算左移/右移
示例 C中的输入输出不再需要像C语言那样手动指定格式流可以自动识别变量类型也能更好的支持自定义类型的输入输出。
例如 3.std(standard) C的标准库放在一个为std的命名空间中cout/cin/endl都属于标准库所以需要通过命名空间std去使用他们。 与命名空间的使用方式相同 1.域作用操作符指定命名空间访问 std::cin a;std::cout a std::endl; 2.using展开频繁使用的成员
#includeiostream
using std::cout;
using std::endl;int main()
{int a 0;std::cin a;cout a endl;return 0;
}3.using展开命名空间项目中不推荐使用推荐日常练习
using namespace std;
四.缺省参数
1.缺省参数的定义 缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。调用该函数时如果并未传输指定的实参则直接采用缺省值否则使用指定的实参缺省参数分为全缺省和半缺省参数。有些地方把缺省参数也叫默认参数
如图 2.全缺省/半缺省 全缺省就是所有形参给缺省值示例 半缺省就是部分下形参给缺省值示例 由于这里是半缺省a没有缺省值所以在调用函数时必须传至少一个参数。 同时C规定半缺省参数必须从右往左依次连续缺省不能间隔跳跃给缺省值。
报错片段 带有缺省参数的函数调用传参时不可跳跃必须从左到右依次给实参。 3.声明与定义 带有缺省参数的函数在声明和定义分离时不能同时给缺省参数规定必须在声明中出现。
五.函数重载 C中支持在同一作用域下同名函数的出现但必须这些函数的形参个数不同形参类型不同或形参类型顺序不同这样可以让函数调用呈现多态行为更加灵活。
1.参数个数不同 2.参数类型不同 3.参数类型顺序不同 函数返回值不同是否能作为重载条件 由于函数名和参数相同在调用函数时无法根据返回值的不同来区分到底要调用哪个函数所以会报错显示函数f重定义。 所以函数返回值不同并不能作为重载条件。
带有缺省参数的函数能构成重载吗 可以看到报错语句为对重载函数的调用不明确说明带有缺省参数的函数构成重载但在函数调用时编译器不知道调用的是哪个函数存在歧义所以会导致报错。
六.引用
1.引用的概念和定义 引用不是定义一个新变量而是给已有的变量取一个别名编译器不会为引用变量开辟空间引用变量与被引用的变量使用同一块内存空间。 类型 引用别名 引用对象 int a 0;int b a;int c a; bc是变量a的别名。这里引用符号与取地址符号相同根据用法区分即可。 int d b; 也可以给别名b取别名为d所以d也是a的别名 由于bcd是a的别名四者同用一块内存空间在d后abcd的值全部自增一并且从运行结果可以看出四个变量的地址相同共用一块空间。
2.引用的特性
2.1引用在定义是必须初始化 2.2一个变量可以有多个引用 2.3引用一旦引用一个实体再不能引用其他实体 3.引用的使用 引用在实际操作中主要用来作引用传参和引用作返回值从而减少拷贝提高效率在改变引用对象的同时改变被引用对象。
3.1引用传参 引用传参与指针传参类似但理解和使用更加简单和方便以Swap函数举例
void Swap(int x, int y)
{int tmp x;x y;y tmp;
}
运行结果 可以看到ab交换了值但与指针不同的是函数体里无需解引用操作因为引用对象与被引用对象使用的是同一块内存空间直接交换即可。
3.2引用作返回值 为了更好的举例在这里我们添加数据结构栈的头文件和源文件代码详细参考栈数据结构中的“时间管理大师” 可以看到在让栈顶加10的操作中出现了报错报错提示为StackTop(st)不是左值说明此时栈顶不可被修改为右值。
分析 在函数返回时操作系统会将返回值储存在一个临时对象中再将临时对象中的值返回因为这个临时对象具有常性所以栈顶不能被修改。那如何才能让这个操作合法呢 在这里我们将引用作返回值并将参数优化为引用参数
// 获取栈顶元素
STDataType StackTop(Stack ps)
{assert(ps._top 0);return ps._a[ps._top - 1];
} 此时函数栈帧销毁后返回对象top并不是存在临时对象中即函数栈帧销毁对返回其引用并无影响故此时栈顶可修改。 为了更深刻的理解引用作返回值的情况再举一个示例 这里可以看到虽然编译器并未报错但是返回值并未加10由于ret存在于函数栈帧中出函数后ret也销毁了所以返回引用结果出现问题。 对于引用返回函数栈帧结束后如果返回对象在函数栈帧中返回引用就会出现问题如果返回对象不在函数栈帧中可以正常返回其引用。
4.const引用 可以引用一个const对象但引用也必须为const对于普通对象也可以进行const引用因为对象的访问权限在引用过程中只可以缩小不能放大。 在类型转换中的const引用 由于在类型转换时操作系统会创建临时对象临时对象具有常性所以在转换时需要用const引用接收。 临时对象 所谓临时对象就是编译器需要⼀个空间暂存表达式的求值结果时临时创建的⼀个未命名的对象 C中把这个未命名对象叫做临时对象 临时对象在以下三种常用情况下会创建 1. 函数传值返回 2.表达式运算 3.类型转换 5.指针和引用的关系 指针与引用在实践中相辅相成在功能上有重叠性但都有各自的特点互相不可替代。 七.inline 1.inline的定义与概念 被inline修饰的函数叫做内联函数在编译时C编译器会在调用的地方展开内联函数这样调用内联函数时就不需要创建函数栈帧了提高了效率。
2.inline的特性 inline适用于频繁调用的短小函数对于递归函数代码量较多的函数加上inline也会被编译器忽略。 通过该段代码的汇编可以看到在调用内联函数Swap时并没有call指令说明Swap函数在调用中已展开根据右边的汇编代码可以进一步验证。 inline不建议声明和定义分离到两个文件分离会导致链接错误因为inline被展开就没有函数地址链接时会报错。 3.inline与宏函数的比较 先来看一段宏函数 对于这个宏函数为了巩固理解需要回答下面三个问题 1.为什么要加分号 宏函数是在预处理时将语句整体替换到调用处如果加了分号分号也会一并调换。 2.为什么加外面的括号 宏函数在与其他式子作运算时需要考虑优先级的问题加了外面的括号保证宏函数优先级更高。 3.为什么加里面的括号 ab各自为一个表达式加了里面的括号保证表达式的优先运算。 从这三个问题可以看出宏函数的实现很复杂且很容易出错不方便调试所以C中设计inline的目的就是为了替代宏函数在提高效率的同时更容易实现不过与宏不同的是inline的展开是在编译而不是预处理阶段使其更容易调试。
八.nullptr NULL实际是一个宏在传统的C头文件(stddef.h)中可以看到如下代码
#ifndef NULL#ifdef __cplusplus#define NULL 0#else#define NULL ((void *)0)#endif
#endif 所以在C中NULL可能会被定义为字面常量0在下面这种情况下与程序的初衷违背 这里func(NULL)的目的是调用func(int* ptr)但却由于NULL被定义成了数字常量0调用成了func(int x)所以如果要调用func(int* ptr)还得对NULL强转类型 但强转类型只能让NULL强转一种类型无法应对变量的多种类型所以C在这里引入了一个关键字nullptr它可以转换成任意其他类型的指针类型。使用nullptr定义空指针可以避免类型转换的问题因为nullptr只能被隐式地转换为指针类型而不能被转换为整数类型。
示例 九.总结 C 的这些基础内容是踏上这门强大编程语言之旅的重要一步。从第一个程序的 “Hello, World!” 开始我们逐步揭开了命名空间、输入输出、缺省参数、函数重载、引用、inline函数以及 nullptr 等关键概念的神秘面纱。这些知识相互关联共同构成了 C 编程的基石。