当前位置: 首页 > news >正文

【C++初阶】速过C++语法基础

文章目录

  • (一)命名空间 namespace
    • (1)namespace的价值
    • (2)namespace的定义
      • ①namespace的形式:
      • ②namespace的本质
        • -C++中的域相关
    • (3)namespace的使用
      • 访问namespace内的内容 ::
      • PS:
        • -头文件和命名空间的展开各自代表什么含义?
  • (二)输入输出
    • (1)输出
    • (2)输入
    • 代码
  • (三)缺省参数
    • (1)全缺省
    • (2)半缺省
  • (四)函数重载
      • 代码:
      • 注意:
      • -偶然发现的编译、链接报错小知识
  • (五)引用
    • (1)定义
    • (2)写法
    • (3)特性
      • 有没有觉得最后两点莫名矛盾?
      • 例题分析
    • (4)使用
    • (5)const引用(常引用)
      • 注意:
      • 指针和引用的区别
  • (六)inline 和 nullptr
    • (1)inline
      • 内联函数的写法
    • (2)nullptr(C++11后才添加)
      • 注:void*和任意类型的指针之间的转换

(一)命名空间 namespace

(1)namespace的价值

一言以蔽之:用于避免命名冲突

原因:同一域中不能定义同名变量。

(2)namespace的定义

①namespace的形式:

1.写在全局处namespace+域名+{ 可以定义变量、函数和类型等(定义/声明) }

namespaceyuan{//定义rand变量intrand=10//定义自定义类型student结构体structstudent{intname;doubleweight;}//定义函数intAdd(intx,inty){returnx+y;}}intmain(){inta=yuan::rand;structyuan::studentp=NULL;printf("%d",Add(1,2));}

不能写在namespace里所有可执行语句(函数调用、循环分支、表达式、赋值语句……) 一旦写了,编译器直接报错;

2.namespace只能定义在全局处,可以嵌套定义;
3.项目工程中多文件的同名namespace会被认为是同一个namespace,不会冲突(逻辑上的合并);
4.C++标准库放在一个名为std(standard)的命名空间里。

②namespace的本质

namespace的本质是定义出一个域,这个域和全局域各自独立。由于不同的域里是可以定义同名变量的,所以命名冲突就可以被解决了。

-C++中的域相关

C++中有局部域、全局域、命名空间域和类域。
域影响编译时语法查找一个变量/函数/类型出处(声明/定义)的逻辑。
全局域和局部域除了会影响查找出处逻辑,还会影响变量的生命周期;命名空间域和类域不影响变量的生命周期。
命名空间内的内容属于全局变量,生命周期是全局的,只是加了一层限制罢了。

(3)namespace的使用

访问namespace内的内容 ::

①指定命名空间单个访问

namespaceyuan{//定义rand变量intrand=10//定义自定义类型student结构体structstudent{intname;doubleweight;}//定义函数intAdd(intx,inty){returnx+y;}}intmain(){//指定命名空间单个访问intr=yuan::rand;//命名空间yuan + 通配符:: + 命名空间内的变量randsturct yuan::student p=NULL;//命名空间中的结构体访问,命名空间yuan和通配符::写在struct和标签名之间printf("%d",Add(1,2));}

PS:

a.如果只使用通配符::,默认访问全局同名变量。(命名空间之外)

b.在嵌套定义中,想访问最里层命名空间的某个内容,就需要逐层使用: :;

#include<stdio.h>namespaceyuan{inta=0;namespaceserverus{intb=10;}}inta=20;intmain(){inta=10;intb=30;printf("%d\n",yuan::serverus::b);}

②using将命名空间内的某个成员展开

#include<stdio.h>namespaceyuan{inta=0;namespaceserverus{intb=10;}}usingyuan::serverus::b;//将yuan命名空间中的serverus命名空间中的b成员展开inta=20;intmain(){inta=10;//int b = 30;//printf("%d\n", yuan::serverus::b);printf("%d",b);//这样就可以直接访问到yuan命名空间中的serverus命名空间中的b了}

③展开命名空间内的所有成员(日常练习可以使用,但实际的项目开发不建议用

#include<stdio.h>namespaceyuan{inta=0;namespaceserverus{intb=10;}}usingnamespaceyuan;//展开yuan命名空间usingnamespaceyuan::serverus;//展开yuan中的serverus命名空间//格式:using namespace + 命名空间名intmain(){//int a = 10;//int b = 30;printf("%d\n",a);printf("%d\n",b);}
-头文件和命名空间的展开各自代表什么含义?

头文件展开:#include 是直接把整个头文件的全部文本,原封不动复制粘贴到当前.c文件里,不管是声明、宏、结构体、注释,全部照搬,不会自动筛选只复制函数声明,更不会复制函数声明对应的函数实现。
(由于初学C++,有些地方习惯先从C的角度理解)

命名空间的展开8:可以理解成打通了一条通向命名空间内部的道路,让编译器找东西时,可以进入命名空间的房间里搜查。

(二)输入输出

【由于作者初学C++,故而只摆概念,不解释。】

< iostream>:是Input Output Stream的缩写,是标准的输⼊、输出流库,定义了标准的输⼊、输出对象(我目前理解它就是一个C++输入输出函数需要包含的头文件,放在std命名空间里)。
std::cin:是istream类的对象,它主要⾯向窄字符(narrow characters (of type char))的标准输⼊流。
std::cout:是ostream类的对象,它主要⾯向窄字符的标准输出流。
std::endl:是⼀个函数,流插⼊输出时,相当于插⼊⼀个换⾏字符加刷新缓冲区(换行作用,类似于C语言中的\n转义字符)。

(1)输出

① <<是流插⼊运算符,>>是流提取运算符。
(C语⾔还⽤这两个运算符做位运算左移/右移)

②使⽤C++输⼊输出更⽅便,不需要像printf/scanf输⼊输出时那样,需要⼿动指定格式,C++的输⼊输出可以⾃动识别变量类型(本质是通过函数重载实现的,这个以后会讲到),其实最重要的是C++的流能更好的⽀持⾃定义类型对象的输⼊输出。

(2)输入

注意:输入用>> , 输出用<< ,不要用反了!

代码

//输入输出#include<iostream>usingnamespacestd;intmain(){inta=10;doubleb=2.5;charc='x';cout<<a<<' '<<b<<' '<<c<<endl;cout<<a<<' '<<b<<' '<<c<<"\n";cout<<a<<' '<<b<<' '<<c<<'\n';cin>>a>>b>>c;cout<<a<<' '<<b<<' '<<c;return0;}

(三)缺省参数


补充解释一下最后一点:如果只有函数定义,在函数定义上写缺省值是合法的,但是如果同时有函数定义和函数声明,那么就规定只能在声明处给缺省值。

文字描述说了也是一知半解,看看具体代码实现:

(1)全缺省

全缺省:调用函数不传任何实参,形参的值全部采用缺省值。

//全缺省#include<iostream>usingnamespacestd;//函数声明intAdd(intx=5,inty=10);intmain(){//函数调用intret=Add();cout<<ret<<endl;return0;}//函数定义intAdd(intx,inty){returnx+y;}


在这里也能看到,想给缺省值,是放到函数声明里的。

(2)半缺省

半缺省:只能从右往左给缺省值,函数调用是实参只能从左往右给。
(理解实参拷贝的顺序,就能明白为啥函数声明里的缺省值是从右往左的了,两者要互补。)

#include<iostream>usingnamespacestd;//半缺省//函数声明//只能从右往左给缺省值intAdd(intx,inty=20);intmain(){intret=Add(2);cout<<ret<<endl;return0;}//函数定义intAdd(intx,inty){returnx+y;}



(四)函数重载

C++⽀持在同⼀作⽤域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数、类型或者顺序不同,对返回值类型和函数体无要求。这样C++函数调⽤就表现出了多态⾏为,使⽤更灵活。C语⾔是不⽀持同⼀作⽤域中出现同名函数的。

好处:C++中有了函数重载,就不需要写一堆逻辑一样但形参不同的函数了。

代码:

返回值无所谓 函数名必须相同 (形参个数、类型或者顺序必须不同)

//函数定义doubleAdd(intx,doubley){returnx+y;}//形参类型不同intAdd(intx,inty){returnx+y;}//形参个数不同intAdd(intx,doubley,intz){returnx+y+z;}//形参顺序不同doubleAdd(doubley,intx)//double Add(double x, int y) 同样可以{returnx+y;}

注意:

①下面三个函数定义不构成重载,它们是完全一样的。

当函数交换顺序的形参是同一类型或者只是改变了形参的名字,这两种情况下,不会构成重载,编译会报错。

intAdd(intx,inty){returnx+y;}intAdd(inty,intx){returnx+y;}intAdd(inta,intb){returna+b;}


②放在不同域内的同名函数不是函数重载。

#include<iostream>usingnamespacestd;//形参类型不同intAdd(intx,inty){returnx+y;}namespaceyuan{intAdd(intx,inty){returnx+y;}intAdd(intx,doubley){returnx+y;}}intmain(){return0;}

一个是全局域一个是命名空间域,当然不会构成重载,这种编译不报错。


-偶然发现的编译、链接报错小知识

在VS中,编译报错是以C开头的,而链接报错是以LNK开头的。



(五)引用

(1)定义

(2)写法

类型&引用别名=引用对象;
#include<iostream>usingnamespacestd;intmain(){inta=9;//b是a变量的别名,b不开空间,b代表a也就是9int&b=a;//c又是b的别名,其实也就是a的别名,依旧不开空间,c也代表a也就是9//可以给别名取别名int&c=b;cout<<a<<endl;cout<<b<<endl;cout<<&a<<endl;cout<<&b<<endl;return0;}

(3)特性

  • 引用在定义时必须初始化;
  • 一个变量可以有多个引用;
  • 别名发生改变了,就是变量发生改变了;
  • 引用一旦引用了一个实体,就不能再引用其他实体。

有没有觉得最后两点莫名矛盾?

—— 既然都不能引用别的实体,有何谈改变呢?

但其实不矛盾。
不能改变一个已经引用了实体的引用去引用其他实体,但是可以改变引用自身的值。简单说就是如果a=10,b是a的引用,那么b可以改变值为20、30,但是b不能成为c的引用。

例题分析

#include<iostream>usingnamespacestd;intmain(){inta=10;int&b=a;intc=20;b=c;//这是让b引用c,还是将c的值赋给b?cout<<b<<endl;cout<<&a<<" "<<&b<<endl;cout<<&c<<" "<<&b<<endl;return0;}


将c的值赋给b,b=20,由于b是a的别名,和它共用同一块存储空间,a的值也会变成20。打印a、b地址时,自然也是一样的地址。


(4)使用

(5)const引用(常引用)

使用指针和引用是间接访问变量,相当于开辟出一条额外的通道,而这条通道的权限是有限制的,它可以缩小但是不能放大,即通过指针、引用访问对象的权限可以不变、缩小,但是不能放大。

#include<iostream>usingnamespacestd;intmain(){//情况一:讲明权限放大的报错情况constinta=10;// a不能被修改int&b=a;//会报错,此时b是a的别名,如果通过b是可以改变a的值的//这说明对象的访问权限放大了constint&rb=a;//不会报错//使用常引用,rb也不能修改,则a访问权限并未发生变化//情况二: 讲明权限缩小的合法情况intc=20;//c变量可以修改constint&rc=c;//不会报错,rc引用不能修改值,也就是不能修改c的值,权限缩小了,但是是合法的//注意: 引用的访问权限不会改变原变量的访问权限rc++;//报错c++;//不报错//情况三:讲明C++中规定临时对象具有常性,不能被修改//临时对象:数值字面量、返回值、表达式的值、类型转换后的值(无论显隐)//数值字面量:int&d=10;//会报错//10是一个临时对象,具有常性,不可修改;生命周期在本语句结束后结束//使用普通引用,一会放大访问权限,二是在本条语句结束后临时对象的空间被销毁了,可它的别名却还存在,会造成“悬空引用”(野引用)//普通引用无法延长临时对象的生命周期,但是常引用可以延长临时对象的生命周期,那常引用什么时候销毁,临时对象就什么时候销毁constint&rd=10;//表达式的值:inte=10;intf=20;int&g=e+f;//会报错,表达式的值会放在一个临时对象里,临时对象具有常性,应该用常引用constint&rg=e+f;//类型转换后的值:inth=10;double&i=h;//会报错,i引用的不是h,而是类型转换后放在临时对象里的值//而临时对象不能修改,它的引用要是常引用constdouble&ri=h;return0;}

注意:

①讲明C++中规定临时对象具有常性,不能被修改。
(临时对象:常量数字、返回值、表达式的值、类型转换后的值)
②普通引用无法延长临时对象的生命周期,但是常引用可以延长临时对象的生命周期,那常引用什么时候销毁,临时对象就什么时候销毁。

const引用的价值不止以上几条,在一些需要用引用接收参数的形参上,也可以使用const,这样就可以接收更多类型的值(常量数字、表达式的值、类型转换后的值、函数返回值…),如果是普通引用就不能接收这些放在临时变量里具有常性的值了(因为这是权限放大,不合法)。

指针和引用的区别


(六)inline 和 nullptr

(1)inline



也就是说针对一些频繁调用的短小函数,可以使用内联,编译器也会听你的,但是如果是一些复杂的函数,即使加上内联,编译器也可能不会听你的。

内联函数的写法

直接在普通函数的返回值前加一个inline就好。

inlineintADD(inta,intb){returna+b;}

(2)nullptr(C++11后才添加)

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

#ifndefNULL#ifdef__cplusplus#defineNULL0#else#defineNULL((void*)0)#endif#endif

可以看到,在C++中,NULL宏定义为0,那么在如下的函数调用时,就会存在问题:

#include<iostream>usingnamespacestd;voidf(intx){cout<<"f(int x)"<<endl;}voidf(int*ptr){cout<<"f(int* ptr)"<<endl;}intmain(){f(0);//调用f(int x)函数f(NULL);// 本想通过f(NULL)调⽤指针版本的f(int*)函数,但是由于NULL被定义成0,调⽤了f(int x),因此与程序的初衷相悖。f((int*)NULL);//成功调用f(int*)函数f((void*)NULL);// 编译报错// void*既不适合int参数,又不适合int*参数——注f(nullptr);//成功调用f(int*)函数return0;}

C++11中引⼊nullptr,nullptr是⼀个特殊的关键字,nullptr是⼀种特殊类型的字⾯量,它可以转换成任意其他类型的指针类型。使⽤nullptr定义空指针可以避免类型转换的问题,因为nullptr只能被隐式地转换为指针类型,⽽不能被转换为整数类型。

注:void*和任意类型的指针之间的转换

在C语言中,void类型的指针和任意类型的指针之间的转换都支持隐式转换,不写强转,编译器也不会报错,但是在C++中,void类型的指针和任意类型的指针之间的转换不支持隐式转换,编译时会报错。除非显示强制类型转换。


初学C++,如有错误,欢迎指出!

——end——

http://www.jsqmd.com/news/1365827/

相关文章:

  • 如何选择可靠的linux核心板?浙江启扬智能科技有限公司深度解析 - 品牌报告
  • 2026加拿大移民中介**评测:持牌资质+全案能力双对标,星旅途移民99.2分登顶 - 互联网科技品牌测评
  • AI视频生成实战:从创意到成片的低成本广告制作全流程
  • 3分钟掌握音乐格式转换技巧:解锁加密音频的完整指南
  • Legacy iOS Kit技术深度解析:iOS设备降级与系统恢复的底层实现原理
  • 2026 年现阶段越秀值得关注的美甲移印机生产厂家哪家好,美甲店小姐姐靠这玩意儿,半天能接二十个单还不磨手? - 企业推荐管【认证】
  • WindowsCleaner终极指南:如何快速彻底解决C盘空间不足问题
  • 抖音批量下载终极指南:如何高效获取无水印短视频内容
  • 宝塔面板快速部署Redis与Node.js集成开发实战指南
  • 佛山性价比高的企业画册哪个靠谱 - GrowthUME
  • 2026年8月温州代理记账公司推荐 - 品牌优企推荐
  • 运动团建行业深度解析:体验式教育赋能企业组织效能的理论与实践 - GrowthUME
  • Django 路由组织、名称空间与虚拟环境
  • 暗黑破坏神2存档编辑器终极指南:免费可视化修改工具完全手册
  • 聚焦搜索整合通义千问:开发者如何利用系统级AI提升工作流效率
  • 机器人量产最后一公里
  • Rust 标准库 `std` 中最常用、最核心的模块和类型
  • 北京团建公司哪家口碑好?HR圈真实评价与验证方法全解析 - 陀螺团建
  • 终极WindowResizer指南:如何强制调整Windows窗口大小解决三大痛点
  • SuperMap空间关系分析在三维GIS属性管理中的应用
  • 2026年气弹簧品牌推荐厂家盘点,优质选择助你轻松选购 - GrowthUME
  • 高效解决WeMod/Wand客户端限制的WandEnhancer技术方案实现
  • 12 — 分支就是便利贴,HEAD 就是指路牌
  • 北京AI搜索优化公司|2026年AI-GEO优化服务商选择指南(附FAQ)甄选
  • 如何快速掌握Subtitle Edit:免费开源字幕编辑器的完整入门指南
  • 从 TCP 90μs 到 SHM 28μs:我的 RPC 框架零拷贝优化历程
  • 2026年Q3大米行业供应厂家实力格局与选型逻辑分析 - 优企名品
  • Kimi转 word 工具推荐:首选「AI 导出鸭」平板版,专为 iPad/安卓平板打造,深度适配 Kimi 等主流 AI,一键无损导出 Word,完整保留公式图表与代码高亮。
  • 广州团建公司哪家口碑好?制造业HR与商贸企业的真实评价怎么看 - 陀螺团建
  • 宿迁汽车音响老店,亲测汽车音响首推宿迁车之友 - GrowthUME