using声明和using指示、std::move和std::forward
2015-08-18 20:13
239 查看
一、using声明和using指示:
写在前面:using指示并非一无是处,例如在命名空间本身的实现文件中就可以使用using指示。
using指示一次性注入某个命名空间的所有名字,这种用法看似简单,实则充满了风险:只使用一条语句就突然将命名空间中所有成员的名字变得可见了。(如果应用程序使用了多个库,而这些库的名字通过using指示变得可见,则全局命名空间污染的问题将重现)
另一个风险是:由using指示引发的二义性错误“只有在使用了冲突名字的地方才能被发现”。这种延后的检测错误意味着可能在特定库引入很久之后才爆发冲突。
相比于使用using指示,在程序中对命名空间的每个成员分别使用using声明效果更好,这么做可以减少注入到命名空间的名字数量。另外,using声明引起的二义性问题在声名出就能被发现,无须等到名字使用的地方,这对检测并修改错误大有益处。
1. using 声明:一个using声明一次只能引入一个命名空间成员,从using声明点开始,直到包含该using声明的作用域结尾,声明的名字仅仅在该作用域是可见的,外部作用域中相同的名字被屏蔽,它可以出现在全局作用域,局部作用域或者命名空间作用域中,类中的using声明局限于使用其基类中定义的名字;
using声明将名字直接放入出现using声明的作用域,好像using声明是命名空间成员的局部别名一样,这种声明是局部化的,名字仅仅在using声明被包含的作用域有效;
一定记住using声明是局部的,它涉及到的作用域只有一个,就是从using声明点开始,直到包含该using声明的作用域结尾,别无他处;
2. using指示:using指示使得特定命名空间的所有名字可见,从using指示点开始(这点同using声明一致),对名字可以不加限定符使用,直到包含using指示的作用域的末尾;using指示具有将命名空间成员提升到包含命名空间本身和usin指示的最近作用域的效果;
二、std::move和std::forward:
通过书写std::move,而不是move,我们使用它们的“带限定语的完整版本”,从而明确地知道想要使用的是“函数的标准库版本”。
标准库中的move函和forward函数,都是模板函数,在标准库的定义中,它们都能接受一个右值引用的函数形参,而在函数模板中,右值引用形参可以匹配任何类型。如果我们自己的应用程序也定义了一个接受单一形参的move函数,则不管该形参是什么类型,应用程序的move函数都将与标准库的move函数版本相冲突。(forward函数也如此)
标准库中的move函数和forward函数执行的是非常特殊的类型操作,应用程序专门修改这两个函数的原有的行为的概率非常小,另外move函数和forward函数的名字冲突要比标准库的其他函数的冲突更频繁,对于move函数和forward函数来说,冲突很多但是大多数是无意的,这一点解释了为什么建议最好使用它们的“带限定语的完整版本”,从而明确地知道想要使用的是“函数的标准库版本”。
写在前面:using指示并非一无是处,例如在命名空间本身的实现文件中就可以使用using指示。
using指示一次性注入某个命名空间的所有名字,这种用法看似简单,实则充满了风险:只使用一条语句就突然将命名空间中所有成员的名字变得可见了。(如果应用程序使用了多个库,而这些库的名字通过using指示变得可见,则全局命名空间污染的问题将重现)
另一个风险是:由using指示引发的二义性错误“只有在使用了冲突名字的地方才能被发现”。这种延后的检测错误意味着可能在特定库引入很久之后才爆发冲突。
相比于使用using指示,在程序中对命名空间的每个成员分别使用using声明效果更好,这么做可以减少注入到命名空间的名字数量。另外,using声明引起的二义性问题在声名出就能被发现,无须等到名字使用的地方,这对检测并修改错误大有益处。
1. using 声明:一个using声明一次只能引入一个命名空间成员,从using声明点开始,直到包含该using声明的作用域结尾,声明的名字仅仅在该作用域是可见的,外部作用域中相同的名字被屏蔽,它可以出现在全局作用域,局部作用域或者命名空间作用域中,类中的using声明局限于使用其基类中定义的名字;
using声明将名字直接放入出现using声明的作用域,好像using声明是命名空间成员的局部别名一样,这种声明是局部化的,名字仅仅在using声明被包含的作用域有效;
一定记住using声明是局部的,它涉及到的作用域只有一个,就是从using声明点开始,直到包含该using声明的作用域结尾,别无他处;
2. using指示:using指示使得特定命名空间的所有名字可见,从using指示点开始(这点同using声明一致),对名字可以不加限定符使用,直到包含using指示的作用域的末尾;using指示具有将命名空间成员提升到包含命名空间本身和usin指示的最近作用域的效果;
二、std::move和std::forward:
通过书写std::move,而不是move,我们使用它们的“带限定语的完整版本”,从而明确地知道想要使用的是“函数的标准库版本”。
标准库中的move函和forward函数,都是模板函数,在标准库的定义中,它们都能接受一个右值引用的函数形参,而在函数模板中,右值引用形参可以匹配任何类型。如果我们自己的应用程序也定义了一个接受单一形参的move函数,则不管该形参是什么类型,应用程序的move函数都将与标准库的move函数版本相冲突。(forward函数也如此)
标准库中的move函数和forward函数执行的是非常特殊的类型操作,应用程序专门修改这两个函数的原有的行为的概率非常小,另外move函数和forward函数的名字冲突要比标准库的其他函数的冲突更频繁,对于move函数和forward函数来说,冲突很多但是大多数是无意的,这一点解释了为什么建议最好使用它们的“带限定语的完整版本”,从而明确地知道想要使用的是“函数的标准库版本”。
相关文章推荐
- 10个前端开发必备的工具或使用方法
- HDOJ 1047 Integer Inquiry (多个大数求和)
- 图形验证码(JSP+Servlet)
- UVA 11997 K Smallest Sums
- Python nltk -- Sinica Treebank
- BZOJ1042
- Delphi 在任务栏隐藏程序图标
- leetcode -day31 Subsets I II
- Autofac 的构造函数注入方式
- NBUT 1220 SPY
- 总线设备驱动模型——设备篇
- Unable to execute dex: Multiple dex files define Lorg/ap (
- 如何激活一个window/dialog && 不能直接对Dialog Box使用SetFocus
- [algorithm] graph algorithm
- N-Queens N皇后问题 DFS
- leetcode之路026 Remove Duplicates from Sorted Arrayy
- dinic 模板
- 斯特林数 组合数
- HDU 5399
- Codeforces Gym 100650C The Game of Efil DFS