C++命名空间和内联函数

news2024/9/30 23:25:22

目录

命名空间

内联函数

概述

特性:


命名空间

在C/C++中,变量,函数和和类这些名称都存在于全局作用域中,可能会导致很多冲突,使用命名空间的目的是对标识符的名称进行本地化,避免命名冲突或名字污染,namespace关键字就是解决这种问题的。如下程序并无问题:

#include<stdio.h>
int rand=0;
int main(){
    printf("%d\n",rand);
    return 0;
}

但是如果在上述代码中加入一段#include<stdlib.h>,因为stdlib.h头文件里面有一个rand的函数,此时就会出现如下错误:

命名冲突(C语言中没有方法可以解决这个问题):

1.我们写的代码跟库冲突

2.我们互相之间写的代码冲突

这时C++中就有了namespace用来定义一个命名空间,语法:namespace 命名空间名{成员},示例如下:

#include<stdio.h>
#include<stdlib.h>
namespace ThisLocality{
	int rand = 0;
}

int main() {
	printf("%d\n", rand);
}

这时就解决命名冲突这个问题,命名空间就像一堵墙把rand围起来了,此时的rand默认访问的是全局就是stdlib.h头文件里面的函数rand,而namespace里的rand就不会被访问了,既然是访问函数rand那么就用%p来打印地址,此时代码运行如下:

此时想访问namespace里面rand,只需要在rand前面加,命名空间名::(域作用限定符)变量名就可以了,示例代码如下:

#include<stdio.h>
#include<stdlib.h>
namespace ThisLocality{
	int rand = 0;
}
int main() {
	printf("%p\n", rand);//访问的是stdlib.h头文件里面的函数
	printf("%d\n", ThisLocality::rand);//此时访问的是bit命名空间里的rand变量
}

此外,命名空间除了可以定义变量也可以定义函数,结构体,还可以嵌套,代码如下:

namespace ThisLocality{
    //定义变量
    int rand=10;
    //定义函数
    int Add(int left,int right){
        return left+right;
    }
    //定义结构体
    struct Node{
        struct Node*next;
        int val;
    };
    
    //嵌套
    namespace ThisLocality2{
        int rand=100;
    }

}

上述几种定义的访问方式如下图:

上述中函数和变量的访问方式只不过就是在名字后面加了()里面放对应的参数,而定义命名空间中的结构体的时候命名空间名是加在结构体名前面的所以是ThisLocality::Node 结构体变量名,最后访问int rand=10;首先要找到命名空间ThisLocality然后再::命名空间名,这是找命名空间里的命名空间最后就到了这个命名空间里了,最后::变量名就可以访问了,我们知道嵌套如果太深也不好一般来说两层基本就够了。

下面在Stack.h中定义了ThisLocality然后在Stack.cpp中完成的ThisLocality里面函数的内容,因为他们是同名所以会自动合并成一个命名空间,所以在Test.cpp中导入Stack.h就可以使用ThisLocality中的函数了。

Stack.cpp中的代码:

#include"Stack.h"
namespace ThisLocality{
    void StackInit(ST*ps){
        ps->a=NULL;
        ps->top=0;
        ps->capacity=0;
    }
    void StackPush(ST*ps,int x){
    //...
    }
}

Stack.h中的代码:

#pragma once
#include<stdio.h>
namespace ThisLocality {
	typedef  struct Stack {
		int* a;
		int top;
		int capacity;
	}ST;
	void StackInit(ST* ps);
	void StackPush(ST*ps, int x);
}

Test.cpp中的代码:

#include<stdio.h>
#include<stdlib.h>
#include"Stack.h"
int main() {
	ThisLocality::ST s;
	Thislocality::StackInit(&s);
	Thislocality::StackPush(&s,1);
	Thislocality::StackPush(&s,2);
	Thislocality::StackPush(&s,3);
	Thislocality::StackPush(&s,4);

}

 展开命名空间,使用展开命名空间就像把命名空间里面的代码直接放到展开位置上了,使用了展开命名空间之后就不需要再使用,命名空间::这段了可以直接使用里面的变量或者函数跟普通变量使用方法并无区别。

using namespace 命名空间名;

展开示例:

可以看到展开之后不需要加,命名空间名::,如其中的ST它会先去全局中找没找到就会去声明的命名空间里面找,如果在这两个地方都没有找到就会报错,但是不建议大量使用这种方法。

我们经常会在很多C++的代码中看到:using namespace std;这段代码,这段代码其实是C++官方库里面的命名空间,这里是直接把这个库展开了,这样就可以随便用里面的东西了。C++把东西放在里面,就是因为容易发生冲突,如果展开那不是本末倒置了,但是日常小程序为了方便可以这样做。

内联函数

概述

以inline修饰的函数叫做内联函数,编译时 C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数是提升程序运行的效率。 

如有一个相加两数的函数:

int ADD(int a,int b){
    return a+b;
}

如果在上述函数前面添加inline关键字将其改成内联函数,在编译期间会替换调用函数体的函数的调用位置。这类似于C语言中的宏的替换:

#include<iostream>
using namespace std;
#define ADD(x,y) ((x)+(y))
#define ADD1(x,y) ((x)+(y));
int main() {
    cout << ADD(23, 87);
    //上述代码中的ADD替换成 宏中的内容 
    //cout<<((23)+(87));


    //宏后面不能加;是因为宏是完全替换的操作如下就会出错
    cout << ADD1(23, 24) << endl;
    //因为其替换之后代码为:
    //cout<<((23)+(24));<<endl;  所以一般不建议在宏后加;
}

宏优点:直接替换调用位置的代码,不用建立函数栈帧,提高效率

宏的缺点:

容易出错,语法细节要求多

而且宏不能调试(在预处理阶段就替换了)

还没有类型的检查(如我传一个int和char会导致结果不理想)

C++中就用:enum const inline来替代宏

enum和const是宏常量

inline是宏函数

而inline却跟正常函数一样,可以调式,有类型检查

使用inline函数的代码如下:

inline int ADD(int a,int b)
{
    int c=x+y;
    return c;
}
int main(){
    int ret1=ADD(23,2);
    //不用建立函数栈帧
    return 0;
}

从上可以看到其语法跟普通函数没有不同只是在函数前面加上了inline。

在release模式下,可以查看编译器生成的汇编代码中是否存在call Add ,而在debug模式下,需要对编译器进行设置,否则不会展开(替换)。

特性:

由上可知inline是一种以空间换时间的做法,如函数被编译器当做内联函数则会在编译阶段,会用函数体替换函数调用,这可能会导致文件变大,但是少了调用开销可以提高程序运行效率。

inline对于编译器来说只是建议,在不同的编译器中inline的实现也有所不同。

inline修饰:函数不是很大(取决于对应的编译器),不是递归,也不频繁调用的函数可以使用inline修饰,不然编译器会忽略inline的特性。

使用inline时并不建议将声明和定义分开,因为这样会导致链接错误,因为inline被展开,然后就没有了函数地址,链接就会找不到。

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

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

相关文章

鸿蒙OpenHarmony开发实战:【MiniCanvas】

介绍 基于OpenHarmony的Cavas组件封装了一版极简操作的MiniCanvas&#xff0c;屏蔽了原有Canvas内部复杂的调用流程&#xff0c;支持一个API就可以实现相应的绘制能力&#xff0c;该库还在继续完善中&#xff0c;也欢迎PR。 使用说明 添加MiniCanvas依赖 在项目entry目录执行…

由浅到深认识Java语言(21):Math类

该文章Github地址&#xff1a;https://github.com/AntonyCheng/java-notes 在此介绍一下作者开源的SpringBoot项目初始化模板&#xff08;Github仓库地址&#xff1a;https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址&#xff1a;https://blog.c…

UE像素流公网(Windows、Liunx)部署无需GPU服务器

@TOC 前言 之前有个前端地图服务项目要改成UE来渲染3D,有需要在云服务器上多实例运行,所以就先研究了Windows版本的像素流云渲染,后来客户的云服务器是Linux版CectOS系统,加上又有了一些后端服务在上面运行了不能重装成Windows,所以就又着手去研究了Linux系统的云渲染。…

【动手学深度学习】深入浅出深度学习之PyTorch基础

目录 一、实验目的 二、实验准备 三、实验内容 1. 数据操作 2. 数据预处理 3. 线性代数 4. 微积分 5. 自动微分 四、实验心得 一、实验目的 &#xff08;1&#xff09;正确理解深度学习所需的数学知识&#xff1b; &#xff08;2&#xff09;学习一些关于数据的实用…

SLAM算法与工程实践——CMake使用(4)

SLAM算法与工程实践系列文章 下面是SLAM算法与工程实践系列文章的总链接&#xff0c;本人发表这个系列的文章链接均收录于此 SLAM算法与工程实践系列文章链接 下面是专栏地址&#xff1a; SLAM算法与工程实践系列专栏 文章目录 SLAM算法与工程实践系列文章SLAM算法与工程实践…

第28章 ansible的使用

第28章 ansible的使用 本章主要介绍在 RHEL8 中如何安装 ansible 及 ansible的基本使用。 ◆ ansible 是如何工作的 ◆ 在RHEL8 中安装ansible ◆ 编写 ansible.cfg 和清单文件 ◆ ansible 的基本用法 文章目录 第28章 ansible的使用28.1 安装ansible28.2 编写ansible.cfg和清…

springboot+vue考试管理系统

基于springboot和vue的考试管理系统 001 springboot vue前后端分离项目 本文设计了一个基于Springbootvue的前后端分离的在线考试管理系统&#xff0c;采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&…

113 链接集10--ctrl+左键单击多选

1.ctrl左键单击多选&#xff0c;单击单选 精简代码 <div class"model-list"><divmousedown.prevent"handleClick(item, $event)"class"model-list-item"v-for"item in modelList":key"item.id":class"{ model…

UE5中各类型的英文名称缩写(直接用于文件前缀)

真正开发项目时用到的素材文件是相当巨量的&#xff0c;在资产中查找时由于不区分文件夹&#xff0c;因此查找是比较头疼的&#xff0c;所以很多同类型的文件名命名时要加入缩写&#xff0c;并且同一对象的不同功能文件也需要用不同命名来区分。 本文提供初学者内容包中的缩写…

奇舞周刊第523期:来自 rust 生态的强烈冲击?谈谈 Leptos 在语法设计上的精妙之处...

奇舞推荐 ■ ■ ■ 来自 rust 生态的强烈冲击&#xff1f;谈谈 Leptos 在语法设计上的精妙之处 过去很长一段时间&#xff0c;前端框架们都在往响应式的方向发展。同时又由于 React hooks 的深远影响&#xff0c;函数式 响应式成为了不少前端心中最理想的前端框架模样。Solid …

vue3对openlayers使用(加高德,天地图图层)

OpenLayers认识 WebGIS四大框架&#xff1a; Leaflet、OpenLayers、Mapbox、Cesium OpenLayers 是一个强大的开源 JavaScript 地图库&#xff0c;专注于提供可嵌入网页的交互式地图体验。作为一款地理信息系统&#xff08;GIS&#xff09;的前端开发工具&#xff0c;OpenLaye…

java设计模式(1)---总则

设计模式总则 一、概述 1、什么是设计模式 设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。 解释下&#xff1a; 分类编目&#xff1a;就是说可以找到一些特征去划分这些设计模式&#xff0c;从而进行分类。 代码设计经验&#xff1a;这句很重…

CRC计算流程详解和FPGA实现

一、概念 CRC校验&#xff0c;中文翻译过来是&#xff1a;循环冗余校验&#xff0c;英文全称是&#xff1a;Cyclic Redundancy Check。是一种通过对数据产生固定位数的校验码&#xff0c;以检验数据是否存在错误的技术。 其主要特点是检错能力强、开销小&#xff0c;易于电路实…

YOLOv8-ROS-noetic+USB-CAM目标检测

环境介绍 Ubuntu20.04 Ros1-noetic Anaconda-yolov8虚拟环境 本文假设ROS和anaconda虚拟环境都已经配备&#xff0c;如果不知道怎么配备可以参考&#xff1a; https://blog.csdn.net/weixin_45231460/article/details/132906916 创建工作空间 mkdir -p ~/catkin_ws/srccd ~/ca…

【javascript】原型继承

在编程中&#xff0c;我们经常会想获取并扩展一些东西。 例如&#xff0c;我们有一个 user 对象及其属性和方法&#xff0c;并希望将 admin 和 guest 作为基于 user 稍加修改的变体。我们想重用 user 中的内容&#xff0c;而不是复制/重新实现它的方法&#xff0c;而只是在其之…

黑马程序员:C++核心编程——2.引用

引用的作用是给变量起别名&#xff0c;本名和别名都可以操作同一块地址的数据。 注意事项 1&#xff09;引用必须初始化且在初始化后不可改变。大白话是创建时不能不说是谁的别名&#xff0c;更不能在创建之后修改为其他人的别名。 2&#xff09;*重点&#xff1a;函数传参的…

蓝桥杯b组C语言组一个月怎么准备?

蓝桥杯b组C语言组一个月怎么准备&#xff1f; C/C程序设计组其中主要的是C算法竞赛选手 1.面对算法竞赛C语言缺少很多便捷性的数据结构&#xff0c;应该快速了解并掌握C的stl。 2.蓝桥杯俗称篮球杯&#xff0c;含金量大海捞针&#xff0c;其中练好dfs的暴力搜索能够骗取相当的…

从信号完整性角度看电容应用与计算

从信号完整性的角度来看&#xff0c;电容在电子电路中具有关键的应用。电容是一种被用来存储电荷并在电路中传递电流的被动元件&#xff0c;它对信号完整性有着重要的影响。 1. 去耦电容的选择 电容类型总结表格 实际的电容并不是理想&#xff0c;表现为&#xff1a; a.电…

网页无插件视频播放器,支持录像、截图、音视频播放,多路播放等,提供源码下载

前言 本播放器内部采用jessibuca插件接口&#xff0c;支持录像、截图、音视频播放等功能。播放器播放基于ws流&#xff0c;分屏操作支持1分屏、4分屏、6分屏、9分屏方式。 jessibuca工作原理是通过Emscripten将音视频解码库编译成Js&#xff08;WebAssembly&#xff0c;简称was…

人工智能的迷惑行为:AI世界的隐秘角落

人工智能迷惑行为大赏 在当今数字化时代&#xff0c;人工智能技术的飞速发展给我们的生活带来了诸多便利和可能性&#xff0c;但同时也伴随着一些令人困惑的现象和行为。本文将深入探讨人工智能的迷惑行为&#xff0c;揭示AI世界中的隐秘角落&#xff0c;让我们一同探寻这个充…