【C++】C++中的ADL机制在使用using namespace时查找混乱问题

目录

一.C++中的ADL是什么

二.C++中的using namespace

三.C++中的ADL和using namespace的联系与区别

四.c++中的ADL与unqualified name


一.C++中的ADL是什么

在C++中,ADL代表“Argument-Dependent Lookup”,即“参数依赖查找”。这是一种机制,允许编译器在查找函数名时,根据传递给函数的参数类型来决定查找的命名空间。简单来说,ADL允许编译器在不同的命名空间中查找与参数类型匹配的函数。

例如,如果你有一个函数重载集,并且你想调用一个函数,其参数类型与某个命名空间中的类型匹配,编译器会优先选择那个命名空间中的函数,而不是全局命名空间中的同名函数。

下面是一个简单的例子来说明ADL的概念:

#include <iostream>
#include <vector>namespace A {struct MyType {};void print(const MyType&) {std::cout << "Print from namespace A" << std::endl;}
}namespace B {struct MyType {};void print(const MyType&) {std::cout << "Print from namespace B" << std::endl;}
}int main() {A::MyType a;B::MyType b;// 这里会调用 A 命名空间中的 print 函数,因为 a 的类型是 A::MyTypeprint(a); // 这里会调用 B 命名空间中的 print 函数,因为 b 的类型是 B::MyTypeprint(b);return 0;
}

在这个例子中, print 函数在两个不同的命名空间中都有定义,并且它们都接受一个 MyType 类型的参数。当调用 print 函数时,ADL机制会根据传递给函数的参数的类型来决定调用哪个命名空间中的 print 函数。这就是为什么在 main 函数中, print(a) 调用了 A 命名空间中的 print 函数,而 print(b) 调用了 B 命名空间中的 print 函数。

二.C++中的using namespace

在C++中, using namespace 是一种声明,它用于将整个命名空间中的所有名称引入到当前作用域中。这意味着在声明 using namespace 之后,你可以在当前作用域中直接使用该命名空间中的任何名称,而无需指定命名空间的前缀。

使用 using namespace 的优点:

1. 简化代码:它允许程序员在不重复书写命名空间前缀的情况下使用其中的名称。

2. 提高可读性:对于熟悉库的程序员来说,可以更容易地阅读和理解代码。

使用 using namespace 的缺点:

1. 名称冲突:如果多个命名空间中存在相同名称的实体, using namespace 可能导致名称冲突。

2. 降低代码清晰度:对于不熟悉库或项目的读者, using namespace 可能使代码难以理解,因

它隐藏了实体的来源。

3. 维护困难:在大型项目中,广泛使用 using namespace 可能使得代码难以维护和调试。

在这个例子中,通过 using namespace std; 声明,我们可以在 main 函数中直接使用 std 命名空间中的 vector 和 cout ,而不需要每次前面都加上 std:: 。

限制 using namespace 的使用:

在大型项目或库的开发中,通常建议避免使用 using namespace ,以防止名称冲突和保持代码的清晰度。

在较小的项目或快速原型开发中, using namespace 可以提高开发效率。

替代方案:

使用特定的 using 声明来引入特定的名称,而不是整个命名空间。例如: using std::vector;  而不是  using namespace std; 。

在需要时,只在局部作用域中使用 using namespace ,以减少潜在的影响范围。

通过这种方式,你可以在享受 using namespace 带来的便利性的同时,减少它可能带来的问题。
 

#include <iostream>
#include <vector>using namespace std;int main() {vector<int> vec; // 直接使用 vector,无需 std:: 前缀vec.push_back(10);cout << vec[0] << endl; // 直接使用 cout,无需 std:: 前缀return 0;
}

三.C++中的ADL和using namespace的联系与区别

查找范围:ADL根据函数调用的参数类型来决定查找的命名空间,而 using 声明是显式地将名称或整个命名空间引入到当前作用域。

名称冲突:使用 using 声明时,如果引入的名称与当前作用域中的名称冲突,会导致编译错误。ADL则根据参数类型来选择正确的函数,即使存在名称冲突。

灵活性:ADL提供了一种灵活的查找机制,允许编译器根据上下文自动选择最合适的函数。 using 声明则需要程序员显式指定要引入的名称。

模板编程:在模板编程中,ADL特别重要,因为它允许模板根据模板参数的类型来查找相关的非模板函数。 using 声明在模板中也可以使用,但需要程序员显式指定。

作用域: using 声明引入的名称在当前作用域和所有嵌套作用域中都可见。ADL的查找顺序则遵循特定的规则,不一定局限于当前作用域。

在实际编程中,合理使用ADL和 using 声明可以提高代码的可读性和可维护性。ADL通常用于需要根据参数类型自动选择函数的场景,而 using 声明则用于简化名称的引用,特别是在使用频繁的命名空间中的名称时。

四.C++中的ADL与unqualified name

在C++中,ADL(Argument-Dependent Lookup)与非限定名称(unqualified name)的关系体现在函数调用解析过程中。当在代码中使用非限定名称调用函数时,编译器会根据函数调用的参数类型来确定应该调用哪个函数,这个过程就是ADL。

非限定名称(Unqualified Name)

非限定名称是没有命名空间或类作用域前缀的名称。当在代码中直接使用函数名而没有指定其所属的命名空间或类时,就使用了非限定名称。例如:

sort(v.begin(), v.end());

在这个例子中, sort 是一个非限定名称,它没有前缀来指明它属于哪个命名空间。

ADL与非限定名称的关系

1. 查找顺序:当使用非限定名称调用函数时,编译器会根据ADL的规则来确定函数的查找顺序。编译器会首先在参数类型的相关命名空间中查找,然后是当前命名空间,最后是全局命名空间。

2. 重载解析:ADL在重载函数的选择中起到关键作用。如果存在多个具有相同非限定名称的函数,编译器会根据参数类型和ADL规则来选择最合适的函数版本。

3. 模板实例化:在模板编程中,ADL特别重要。当模板函数使用非限定名称调用其他函数时,ADL规则决定了应该实例化哪个版本的函数。

4. 隐式引用:使用非限定名称时,实际上是隐式地告诉编译器根据参数类型来查找对应的函数,这是ADL的直接应用。

考虑以下代码:

在这个例子中, sort 是一个非限定名称。由于 v 是 std::vector<int> 类型,编译器会根据ADL规则在 std 命名空间中查找 sort 函数,因此会调用 std::sort 而不是全局或 A 命名空间中的 sort 。

#include <algorithm> // std::sort 的声明
#include <vector>namespace A {void sort() {// ...}
}void sort() {// ...
}int main() {std::vector<int> v;// 使用非限定名称调用 sort,ADL 和 using directive 会决定调用哪个 sortsort(v.begin(), v.end());
}

ADL是C++名称查找机制的一部分,它与非限定名称紧密相关,因为非限定名称的解析依赖于ADL来确定正确的函数版本。这种机制增加了C++的灵活性和表达能力,尤其是在模板编程和多命名空间环境下。

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

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

相关文章

探索与维护Hadoop:掌握高效目录查询与清理的艺术

在大数据处理的世界里&#xff0c;Apache Hadoop无疑扮演着举足轻重的角色&#xff0c;提供了一个可靠且可扩展的分布式存储和计算框架。然而&#xff0c;随着数据量的不断膨胀&#xff0c;Hadoop文件系统&#xff08;HDFS&#xff09;中的目录管理与垃圾清理成为数据工程师们不…

汇编教程2

本教程主要教大家如何安装32位Linux虚拟机&#xff0c;为后续实验拆炸弹做准备 下载系统映像文件 以Ubuntu14.04.6系统为例 官方网站&#xff1a;下载地址 点击下载图中32位系统 如果官网进不去可以使用镜像网站 清华镜像网站&#xff1a;下载地址 进入之后找到下图中链接…

redis server response timeout(3000ms) occurred after 3 retry attempts异常分析

读取redis数据报超时错误&#xff1a; Redis server response timeout (3000 ms) occured after 3 retry attempts2024-07-18 17:07:57.124 ERROR [e8f07b0a671c08311dff589827897232] [http-nio-9528-exec-6] c.z.i.u.m.c.e.BaspUserExceptionHandler.exceptionHandler:83 - R…

PyTorch 深度学习实践-基于SoftMax的多分类

视频指路 参考博客笔记 参考笔记二 文章目录 上课内容代码实现作业实现 上课内容 softmax能输出一个分布&#xff1a;每一个输出值>0&#xff0c;且和1 说明&#xff1a; 1、softmax的输入不需要再做非线性变换&#xff0c;也就是说softmax之前不再需要激活函数(relu)。so…

基于X86+FPGA+AI的远程医疗系统,支持12/13代 Intel Core处理器

工控主板&#xff1a;支持12/13代 Intel Core处理器&#xff0c;适用于远程医疗系统 顺应数字化、网络化、智能化发展趋势&#xff0c;国内医疗产业改革正在积极推进&#xff0c;远程医疗、智慧医疗等新模式新业态创新发展和应用&#xff0c;市场空间不断扩大&#xff0c;而基…

Web前端Promise

Promise介绍与使用 Promise是什么&#xff1f; 1.抽象表达&#xff1a; Promise是一门新的技术&#xff08;ES6规范&#xff09;Promise是JS中进行异步编程的新解决方案备注&#xff1a;旧方案是单纯使用回调函数 2.具体表达&#xff1a; 从语法上来说&#xff1a;Promise…

Android SurfaceView 组件介绍,挖洞原理详解

文章目录 组件介绍基本概念关键特性使用场景 SurfaceHolder介绍主要功能使用示例 SurfaceView 挖洞原理工作机制 使用SurfaceView展示图片示例创建一个自定义的 SurfaceView类在 Activity 中使用 ImageSurfaceView注意事项效果展示 组件介绍 在 Android 开发中&#xff0c;Sur…

HiFi-GAN——基于 GAN 的声码器,能在单 GPU 上生成 22 KHz 音频

拟议的 HiFiGAN 可从中间表征生成原始波形 源码地址&#xff1a;https://github.com/NVIDIA/DeepLearningExamples 论文地址&#xff1a;https://arxiv.org/pdf/2010.05646.pdf 研究要点包括 **挑战&#xff1a;**基于 GAN 的语音波形生成方法在质量上不及自回归模型和基于流…

纯前端小游戏,4096小游戏,有音效,Html5,可学习使用

// 游戏开始运行create: function(){this.fieldArray [];this.fieldGroup this.add.group();this.score 0;//4096 增加得分this.bestScore localStorage.getItem(gameOptions.localStorageName) null ? 0 : localStorage.getItem(gameOptions.localStorageName);for(var …

vscode及pycharm配置Python文件模板

一、vscode配置方法 第一步&#xff0c;依次点击“File”->“preference”->“Configure User Snippets”&#xff0c;在弹出的框中输入Python&#xff0c;打开python.json 文件 第二步&#xff0c;python.json 文件中输入以下内容&#xff1a; {"Python Template…

QtC++ 设计模式(五)——状态模式

状态模式 序言理解源码 序言 设计模式只是一个抽象的设计模式方法&#xff0c;并不是一个固定使用的搭配&#xff0c;就算是普通switch语句&#xff0c;Map&#xff0c;乃至状态机都是状态模式的其中一种实现方法 状态模式看起来好像和策略模式差不多&#xff0c;主要是其的侧…

快速上手绿联私有云UGOS Pro系统Docker

要快速上手使用绿联私有云UGOS Pro系统上的Docker&#xff0c;可以按照以下步骤进行操作&#xff1a; 1. 设置绿联私有云UGOS Pro 确保你已经成功设置并连接了绿联私有云设备。完成基本的网络配置和用户设置。 2. 访问UGOS Pro系统 通过浏览器访问你的绿联私有云管理界面。…

git记住账号和密码

git记住账号和密码 一、git记住账号和密码1. 全局记住2. 取消全局记住 一、git记住账号和密码 在使用 git 使用 https推送的时候一直需要输入密码。就可以试试下面的方法 1. 全局记住 windows 在git bash 中执行以下命令 linux 直接在bash中执行 git config --global crede…

深入探讨:Node.js、Vue、SSH服务与SSH免密登录

在这篇博客中&#xff0c;我们将深入探讨如何在项目中使用Node.js和Vue&#xff0c;并配置SSH服务以及实现SSH免密登录。我们会一步步地进行讲解&#xff0c;并提供代码示例&#xff0c;确保你能轻松上手。 一、Node.js 与 Vue 的结合 1.1 Node.js 简介 Node.js 是一个基于 …

Java记事本工具Notepad++

常见的高级记事本 Editplus、Notepad、Sublime Notepad软件的安装和使用 安装&#xff1a;傻瓜式安装 1、选择中文-->【OK】 2、点击【下一步】 3、协议点击【我接受】 4、选择安装路径-->【下一步】 5、点击【下一步】 6、最后点击【安装】 7、将运行取消-->点击…

戴尔电脑开机出现no boot device found错误提示原因分析及解决方法

戴尔电脑是一款不的品牌,戴尔电脑一直以来都是以IT直销享誉全球的。而旗下的戴尔笔记本&#xff0c;更是深受用户们的追捧和喜爱。最近有网友反馈戴尔电脑开机出现no boot device found错误提示是怎么回事&#xff1f;后来发现有很多网友将引导模式改成legacymbr后发现启动时出…

Python 中的属性和方法

在面向对象编程&#xff08;OOP&#xff09;中&#xff0c;类是代码的基本构造块。类通过属性和方法来定义对象的状态和行为。在 Python 中&#xff0c;属性和方法是定义类时的重要组成部分。本文将深入探讨 Python 中的属性和方法&#xff0c;帮助你更好地理解它们的用法和意义…

2024-07-18 Unity插件 Odin Inspector8 —— Type Specific Attributes

文章目录 1 说明2 特定类型特性2.1 AssetList2.2 AssetSelector2.3 ChildGameObjectsOnly2.4 ColorPalette2.5 DisplayAsString2.6 EnumPaging2.7 EnumToggleButtons2.8 FilePath2.9 FolderPath2.10 HideInInlineEditors2.11 HideInTables2.12 HideMonoScript2.13 HideReferenc…

对消息队列进行深入学习

目录 1.什么是消息队列。1.1消息队列1.1.1同步的理解1.1.2异步的理解 1.2消息传递与消息队列 2. 消息队列应用场景2.1 异步处理2.2 流量削锋2.3 应用解耦2.4 日志处理2.5 消息通讯2.6 延时任务2.7 广播消费2.8 分布式事务 3. 主流消息队列3.1 RabbitMQ3.1.1 RabbitMQ工作原理3.…

河南萌新联赛2024第(一)场:河南农业大学(部分题解)

A 造数 题目链接 题意&#xff1a; 给一个整数n&#xff0c;求出最少的操作数使0转化为n 有三种操作方式&#xff1a; 12*2 解题思路&#xff1a; 我们可以将基础的1&#xff0c;2&#xff0c;3分别需要1&#xff0c;1&#xff0c;2次操作&#xff0c; 当n大于3时&#x…