C++语法基础(一)

第一个C++程序

1. <iostream>(C++)

<iostream> 是 C++ 标准库中的头文件,用于处理输入输出操作。它提供了基于流(stream)的输入输出机制。

特点:
  • 面向对象:C++ 中的输入输出操作是基于流的,这种机制是面向对象的。流可以看作是字节序列的抽象,输入流从数据源(如键盘或文件)读取数据,输出流将数据写入目标(如屏幕或文件)。
  • 常用的流对象
    • std::cin:标准输入流,通常与键盘关联,用于从用户输入读取数据。
    • std::cout:标准输出流,通常与显示器关联,用于输出数据到屏幕。
    • std::cerr:标准错误流,通常与显示器关联,用于输出错误信息。
    • std::clog:标准日志流,用于输出日志信息。

2. <stdio.h>(C)

<stdio.h> 是 C 标准库中的头文件,用于处理输入输出操作。它提供了一些用于文件操作和标准输入输出的函数。

特点:
  • 基于函数的输入输出:C 语言中的输入输出操作是基于函数的。常见的输入输出函数包括 printfscanffprintffscanffgetsfputs 等。
  • 低级别:与 C++ 的面向对象的流相比,C 的输入输出更为低级,操作更加直接。
//#include<stdio.h>
#include<iostream>int main(){// printf("hello world\n");std::cout << "hello world" << std::endl;return 0;
}

  我们可以先暂时理解为endl \n 一样,功能就是输出时换行,它们有一些重要的区别,endl 是 C++ 标准库中的一个操控符(manipulator),它不仅用于在输出流中插入一个换行符,还会刷新输出缓冲区(flush the output buffer)。这意味着,endl 会强制将缓冲区中的内容立即输出到目标设备(如屏幕),而不仅仅是插入一个换行符。对于作用限定符::我们可以先简单地理解为什么中的什么。

命名空间

        命名空间(namespace) 是 C++ 中用于组织代码的一种机制,它允许将代码分组到不同的命名空间中,以避免名称冲突,特别是在大型项目或使用多个库时。命名空间为变量、函数、类等标识符提供了一个作用域,可以防止不同命名空间中的标识符相互干扰。

代码演示

#include<iostream>
namespace ICBC{int g_money = 0;void pay(int money){g_money -= money;}void save(int money){g_money += money;}
}
namespace CCB{int g_money = 0;void pay(int money){g_money -= money;}void save(int money){g_money += money;}
}int main(){ICBC::pay(1000);ICBC::save(3000);CCB::save(10000);CCB::pay(2000);std::cout << "工行卡的余额:" << ICBC::g_money << std::endl;std::cout << "建行卡的余额:" << CCB::g_money << std::endl;
}

        在使用命名空间后,相同名字的变量和函数并没有发生冲突

名字空间声明

代码演示

//名字空间声明
#include<iostream>
using namespace std;
namespace ns{int v_tomato = 10;
}
int main(){int v_tomato = 30;using ns::v_tomato; //从这行代码开始,ns中的内容引入当前作用域(相当于定义)//上面的定义会造成重定义报错v_tomato = 20;  cout << "ns::v_tomato = " << ns::v_tomato << endl;return 0;
}

        因为所有标准库提供的 类型、对象和函数都位于std名字空间 ,所以我们在使用using namespace std;后,就可以对输出代码的写法进行简化,省略std::

 代码分析 

         编译器在编译每一个函数时都会构造两张表,在编译这个函数(main函数)结束后销毁。在函数体内定义的变量会放进定义表,对于函数体外定义的对本函数可见的变量会放进可见表。对于本例,使用名字空间声明也相当于在这个函数体内定义了这个变量,又因为函数体内先前已经定义了这个变量(int v_tomato=30),此时的名字空间声明会造成重定义,这是编译器绝对不允许的,因此会报错。当在函数内使用某个标识符时,如果存在同名,编译器需要确定你使用的是哪一个标识符,因此他会拿着这个名字先在定义表中查看,如果定义表中找不到,才会到可见表中找。

名字空间指令(using namespace [...])

        名字空间指令是指使用 using namespace 语句将整个命名空间引入当前作用域。这意味着命名空间中的所有标识符都可以直接使用,而不必再通过命名空间限定符来引用。这种方式在简化代码的同时也可能带来名称冲突的风险,尤其是在大型项目中。 

代码演示

//名字空间指令
#include<iostream>
using namespace std;
namespace ns{int v_tomato = 10;
}
int main(){using namespace ns; //从这行代码开始,ns中的内容在当前作用域中可见//ns::v_tomato = 20;v_tomato = 20;//std::cout << ns::v_tomato << std::endl;cout << "ns::v_tomato = " << ns::v_tomato << endl;return 0;
}

在上面的代码中,using namespace ns; 是一个名字空间指令,它将 ns1命名空间中的所有标识符引入到 main 函数的作用域中,因此你可以直接使用 v_tomato 而不需要在前面加上 ns::。 

 代码分析(不同于上个代码)

         对于本例,代码的输出结果依然是10,我们来分析一下。main函数内的int v_tomato = 10,这是一个放在定义表的局部变量,而对于ns命名空间的int v_tomato = 10是放在可见表中的。当出现v_tomato = 20这个变量,编译器需要确定究竟是这两个同名变量中的哪一个,编译器会先在定义表中寻找,此时他找到了就不会查看可见表,因此v_tomato = 20修改的是main函数内定义的局部变量而不是ns命名空间的同名变量。这也就是最后我们的输出结果依然是v_tomato = 10的原因,因为它实际上并没有修改我们ns命名空间中的这个变量。

 名字空间指令和名字空间声明的差别

        使用名字空间指令会让所指定命名空间的内容在当前作用域中可见,其中定义的变量会被放入可见表中,而使用名字空间声明会让所指定命名空间中的内容引入当前作用域(相当于定义),其中定义的变量放入定义表中

代码演示

//名字空间指令 和 名字空间声明 的差别
#include<iostream>
using namespace std;
namespace ns1{int g_money = 10;int g_other = 10;
}
namespace ns2{int g_money = 10;int g_other = 10;
}
int main(){using namespace ns1;//ns1中的所有内容都出现在可见表中using ns2::g_other;//只有ns2::g_other出现在定义表中g_money = 100;//修改的是ns1中的g_moneycout << "ns1::g_money = " <<ns1::g_money <<", ns2::g_money =" << ns2::g_money <<endl;g_other = 100;//修改的是ns2中的g_othercout << "ns1::g_other =" << ns1::g_other <<", ns2::g_other =" << ns2::g_other <<endl;return 0;
}

命名空间的嵌套

        在C++中,嵌套命名空间的同名变量不冲突,因为每个变量在其所属的命名空间中都有唯一的作用域。变量的名称相同,但由于它们位于不同的命名空间中,编译器可以通过命名空间限定符(如ns1::ns2::g_money)来区分它们。因此,它们不会冲突。

//命名空间的嵌套
#include<iostream>
using namespace std;namespace ns1{int g_money = 10;namespace ns2{int g_money = 20;namespace ns3{int g_money = 30;namespace ns4{int g_money = 40;}}}
}int main(){//名字空间别名可以简化书写namespace ns_forth = ns1::ns2::ns3::ns4;//cout << ns1::ns2::ns3::ns4::g_money << endl;cout << ns_forth::g_money << endl;
}

扩展

        我们说使用名字空间声明引入的变量相当于定义在main函数中的变量,那他们有什么区别?

在C++中,namespace中的变量(如ns::v_tomato)通常具有进程级生命周期

1. 进程级生命周期的定义

  • 进程级生命周期的变量从程序开始执行(通常是在程序的初始化阶段)到程序结束时一直存在。
  • 这些变量通常分配在全局/静态数据区中,生命周期贯穿整个程序的运行过程。

2. namespace中的变量的生命周期

  • namespace ns { int v_tomato = 10; }
    • 这里的v_tomato是在命名空间ns中定义的全局变量。
    • 虽然它被封装在namespace中,但它的本质仍是一个全局变量。
特点:
  • 存储位置v_tomato会存储在全局/静态数据区中,而不是栈或堆中。这意味着它在程序的整个生命周期内都存在。
  • 生命周期:从程序启动时开始(即在main()函数执行之前),直到程序终止时结束。因此,它具有进程级的生命周期。
  • 作用范围:虽然v_tomato的作用范围被限制在命名空间ns中,但它仍然是一个全局变量。这意味着在程序的任何地方,只要通过ns::v_tomato访问,它都可以被引用和修改。

3.示例分析 

#include <iostream>namespace ns {int v_tomato = 10; // 进程级生命周期的变量
}int main() {std::cout << "v_tomato = " << ns::v_tomato << std::endl; // 输出 10ns::v_tomato = 20;std::cout << "v_tomato = " << ns::v_tomato << std::endl; // 输出 20return 0;
}

在这个示例中:

  • v_tomato 在程序开始时被初始化为10,并且在整个程序的生命周期中都存在。
  • 你可以在main()函数中(或程序的其他地方)访问和修改它的值。
  • 当程序结束时,v_tomato才会被销毁。

4. 总结

  • namespace中的变量v_tomato 是具有进程级生命周期的全局变量。
  • 它从程序启动时初始化,并在程序结束时销毁。
  • 尽管被封装在namespace中,它的生命周期和其他全局变量一样,不受namespace本身的影响。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/52941.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

hyperf json-rpc

安装 安装docker hyperf 安装 hyperf-rpc-server-v8 &#xff08;服务端&#xff09; docker run --name hyperf-rpc-server-v8 \ -v /www/docker/hyperf-rpc-server:/data/project \ -w /data/project \ -p 9508:9501 -it \ --privileged -u root \ --entrypoint /bin/sh \…

Swift 可选类型

Swift 可选类型 Swift 是一种强类型编程语言,它在类型安全方面做了很多工作,以确保代码的稳定性和可靠性。在 Swift 中,可选类型(Optional)是一种特殊的类型,用于处理值可能缺失的情况。本文将详细介绍 Swift 中的可选类型,包括其定义、使用场景、语法以及如何正确地处…

Upload-LABS通关攻略【1-20关】

Pass-01 第一关是前端JS绕过 上传一个php文件显示只能上传特定后缀名的文件 这里将1.php改为1.jpg直接进行抓包&#xff0c;在数据包中将jpg改为php放行 文件上传成功&#xff0c;邮件图片新建页面打开 可以访问到1.php文件&#xff0c;则一句话密码上传成功 使用蚁剑 进行连接…

Redux的中间件原理分析

Redux的中间件原理分析 redux的中间件对于使用过redux的各位都不会感到陌生&#xff0c;通过应用上我们需要的所有要应用在redux流程上的中间件&#xff0c;我们可以加强dispatch的功能。最近抽了点时间把之前整理分析过的中间件有关的东西放在这里分享分享。本文只对中间件涉…

音视频开发之旅(90)-Vision Transformer论文解读与源码分析

目录 1.背景和问题 2.Vision Transformer(VIT)模型结构 3.Patch Embedding 4.实现效果 5.代码解析 6.资料 一、背景和问题 上一篇我们学习了Transformer的原理&#xff0c;主要介绍了在NLP领域上的应用&#xff0c;那么在CV(图像视频)领域该如何使用&#xff1f; 最直观…

C# 获取当前鼠标位置

在C#中&#xff0c;获取当前鼠标位置可以通过多种方式实现&#xff0c;但最常见和直接的方法之一是使用System.Windows.Forms命名空间中的Cursor类或者Control类的PointToClient&#xff08;如果你正在处理WinForms应用程序&#xff09;或Windows.UI.Core.CoreWindow的PointerP…

Java源码学习之高并发编程基础——AQS源码剖析之阻塞队列(下)

1.前言&目录 前言&#xff1a; 在上一篇文章AQS源码剖析之阻塞队列&#xff08;上&#xff09;中介绍了以独占锁模式下AQS的基本原理&#xff0c;AQS仅仅起到了一个“维持线程等待秩序”的作用&#xff0c;那么本篇文章继续讲解共享锁模式下的特点。 AQS不操纵锁的获取或者…

算法复盘——LeetCode hot100:哈希

文章目录 哈希表哈希表的基本概念哈希表的使用1. 插入操作2. 查找操作3. 删除操作 哈希表的优点和缺点1.两数之和复盘 242.有效的字母异位词复盘 49.字母异位词分组复盘 128. 最长连续序列复盘HashSet 哈希表 先来搞清楚什么是哈希表吧~ 概念不清楚方法不清楚怎么做题捏 哈希表…

问:说一下Java中数组的实例化方式有哪些?

在Java中&#xff0c;数组的实例化可以通过多种方式完成。以下是五种不同的实例化数组的方式。 1. 直接初始化 这种方式在声明数组的同时&#xff0c;直接初始化数组的元素。 // 示例&#xff1a;直接初始化一个整型数组 int[] numbers {1, 2, 3, 4, 5}; // 解释&#xff1…

使用mysql保存密码

登录MySQL 这行命令告诉MySQL客户端程序用户root准备登录&#xff0c;-p表示告诉 MySQL 客户端程序提示输入密码。 mysql -u root -p创建数据库 create database wifi; use wifi;create table password(user_password CHAR(8),primary key(user_password));源码 代码编译 …

C#——类与结构

在未学习面向对象语言时&#xff0c;我常常将类比作一种结构体&#xff0c;其实类与结构体也确实很相似&#xff0c;类用来做函数的集合&#xff0c;结构用来做变量的集合&#xff0c;接下来将从几个角度刨析类与结构的不同。 类 vs 结构 类和结构在设计和使用时有不同的考虑…

学习记录:js算法(二十):子数组最大平均数 I、无重复字符的最长子串

文章目录 子数组最大平均数 I我的思路网上思路 无重复字符的最长子串我的思路网上思路 总结 子数组最大平均数 I 给你一个由 n 个元素组成的整数数组 nums 和一个整数 k 。 请你找出平均数最大且 长度为 k 的连续子数组&#xff0c;并输出该最大平均数。 任何误差小于 10-5 的答…

QT实战项目之音乐播放器

项目效果演示 myMusicShow 项目概述 在本QT音乐播放器实战项目中&#xff0c;开发环境使用的是QT Creator5.14版本。该项目实现了音乐播放器的基本功能&#xff0c;例如开始播放、停止播放、下一首播放、上一首播放、调节音量、调节倍速、设置音乐播放模式等。同时还具备搜索功…

Centos 下载和 VM 虚拟机安装

1. Centos 下载 阿里云下载地址 centos-7.9.2009-isos-x86_64安装包下载_开源镜像站-阿里云 2. VM 中创建 Centos 虚拟机 2.1 先打开 VM 虚拟机&#xff0c;点击首页的创建新的虚拟机 2.2 选择自定义&#xff0c;然后点击下一步。 2.3 这里默认就好&#xff0c;继续选择下一…

docker加速配置 daemon.json

配置docker 加速 提高下载速度 在某些地区&#xff0c;尤其是中国&#xff0c;Docker Hub 的访问速度可能较慢&#xff0c;导致镜像下载时间过长。通过配置加速器&#xff0c;可以显著提高镜像的拉取速度&#xff0c;减少等待时间。 减少网络不稳定带来的影响 网络不稳定可能导…

gitlab SSH的使用

一、 安装git bash https://git-scm.com/download/win 下载windows 版本&#xff0c;默认安装即可。 二、使用命令 打开本地git bash,使用如下命令生成ssh公钥和私钥对 ssh-keygen -t rsa -C ‘xxxxxx.com’ 然后一路回车 (-C 参数是你的邮箱地址) 若是想输入密码可以输入…

算法-最长连续序列

leetcode的题目链接 这道题的思路主要是要求在O&#xff08;n)的时间复杂度下&#xff0c;所以你暴力解决肯定不行&#xff0c;暴力至少两层for循环&#xff0c;所以要在O&#xff08;n)的时间复杂度下&#xff0c;你可以使用HashSet来存储数组&#xff0c;对于每个数字&#…

黑马JavaWeb开发笔记07——Ajax、Axios请求、前后端分离开发介绍、Yapi详细配置步骤

文章目录 前言一、Ajax1. 概述2. 作用3. 同步异步4. 原生Ajax请求&#xff08;了解即可&#xff09;5. Axios&#xff08;重点&#xff09;5.1 基本使用5.2 Axios别名&#xff08;简化书写&#xff09; 二、前后端分离开发1. 介绍1.1 前后台混合开发1.2 前后台分离开发方式&…

Docker续6:容器网络

1.bridge-utils 一个用于Linux系统的网络桥接工具集。它提供了一些命令行工具&#xff0c;帮助用户创建、管理和配置网络桥接。网络桥接是一种将多个网络接口连接在一起&#xff0c;以使它们能够作为单个网络段进行通信的技术。 bridge-utils 常用的命令包括&#xff1a; b…

【 OpenHarmony 系统应用源码魔改 】-- Launcher 之「桌面布局定制」

前言 阅读本篇文章之前&#xff0c;有几个需要说明一下&#xff1a; 调试设备&#xff1a;平板&#xff0c;如果你是开发者手机&#xff0c;一样可以加 Log 调试&#xff0c;源码仍然是手机和平板一起分析&#xff1b;文章中的 Log 信息所显示的数值可能跟你的设备不一样&…