为了账号安全,请及时绑定邮箱和手机立即绑定

使用STD名称空间

使用STD名称空间

C++
郎朗坤 2019-06-24 11:02:27
使用STD名称空间对于STD名称空间使用“似乎有不同的看法。有人说用‘using namespace std,另一些人则说,不要使用前缀STD函数,这些函数将与‘一起使用。std::“当其他人说使用类似的东西时:using std::string;using std::cout;using std::cin;using std::endl;using std::vector;对于将要使用的所有STD函数。每种方法的优缺点是什么?
查看完整描述

3 回答

?
阿波罗的战车

TA贡献1862条经验 获得超6个赞

排除基本内容(必须添加std:infront所有stl对象/函数,如果没有“使用命名空间std”,则冲突的可能性更小)

同样值得注意的是,你永远不应该

using namespace std

在头文件中,因为它可以传播到包含该头文件的所有文件,即使它们不想使用该名称空间。

在某些情况下,使用这样的东西是非常有益的

using std::swap

好像有一个专门的交换版本,编译器将使用它,否则它将回到std:swp上。

如果调用std:swp,则始终使用基本版本,它不会调用优化版本(如果存在的话)。


查看完整回答
反对 回复 2019-06-24
?
侃侃尔雅

TA贡献1801条经验 获得超16个赞

首先,一些术语:

  • 使用-声明using std::vector;

  • 使用指令using namespace std;

我觉得用使用-指令只要它们不在头文件的全局范围内使用,就可以了。所以

using namespace std;

在您的.cpp文件中并不是一个真正的问题,如果结果是,它完全在您的控制之下(如果需要,甚至可以将它的作用域限定为特定的块)。我看不出有什么不合理的理由把代码弄得乱七八糟。std::限定符-它只是一堆视觉噪音。但是,如果您没有使用std在您的代码中,我也没有发现遗漏指令的问题。这是一个重言式-如果指令没有必要,那么就没有必要使用它。

同样的,如果你能用几个使用-声明(而不是使用-指令)中的特定类型。std命名空间,那么就没有理由不将那些特定的名称引入到当前的命名空间中。出于同样的原因,我认为这将是疯狂和簿记麻烦,有25或30个使用-声明,而一个单一的使用指令将发挥同样的作用。

同时也要记住,有时候使用声明。参考ScottMeyers的“项目25:考虑支持非抛出交换”,从有效C+,第三版。为了使泛型的模板化函数使用参数化类型的“最佳”交换方法,需要使用声明和参数依赖查找(也称为ADL或Koenig查找):

template< typename T >void foo( T& x, T& y){
    using std::swap;     // makes std::swap available in this function

    // do stuff...

    swap( x, y);         // will use a T-specific swap() if it exists,
                         //  otherwise will use std::swap<T>()

    // ...
 }

我认为我们应该研究各种语言的常见习语,这些语言大量使用了名称空间。例如,Java和C#在很大程度上使用名称空间(可以说比C+更容易使用)。在这些语言中,名称空间中使用名称的最常见方式是将它们以相当于使用指令的形式统合到当前的作用域中。这不会引起广泛的问题,而且问题的几次是在“异常”的基础上通过完全限定的名称或别名来处理的,就像在C+中所做的那样。

Herb Sutter和Andrei Alexandrescu在他们的书“C+编码标准:101规则、准则和最佳实践”中的“第59项:不要在头文件中或在#include之前编写名称空间用法”中这样说:

简单地说:您可以而且应该在实现文件中自由地使用声明和指令之后的命名空间。#include指示和感觉很好。尽管重复了相反的断言,使用声明和指令的命名空间并不是邪恶的,它们也没有违背名称空间的目的。相反,它们是使名称空间可用的原因。

Stroupstrup在“C+编程语言第三版”中经常被引用为“不要污染全局名称空间”。他确实说过(C.14[15]),但提到了C.10.1章,其中他说:

使用-声明将名称添加到本地范围。一个使用指令不;它只是在声明名称的作用域中呈现可访问的名称。例如:

namespaceX {
    int i , j , k ;}int k ;void f1(){
    int i = 0 ;

    using namespaceX ; // make names from X accessible

    i++; // local i
    j++; // X::j
    k++; // error: X::k or global k ?

    ::k ++; // the global k

    X::k ++; // X’s k}void f2(){
    int i = 0 ;

    using X::i ; // error: i declared twice in f2()
    using X::j ;
    using X::k ; // hides global k

    i++;
    j++; // X::j
    k++; // X::k}

本地声明的名称(由普通声明或使用声明)隐藏同名的非本地声明,并且在声明点检测到名称的任何非法重载。

注意歧义错误k++在……里面f1()..全局名称不优先于全局范围内可访问的名称空间中的名称。这提供了防止意外名称冲突的重要保护,而且-重要的是-确保不会从污染全局命名空间中获得任何好处。

当声明许多名称的库可以通过使用-指令访问时,未使用名称的冲突不被视为错误,这是一个很大的优势。

...

我希望与传统的C和C+程序相比,在使用名称空间的新程序中使用全局名称的情况会大大减少。名称空间的规则是专门为“懒散”的全局名称用户制定的,而不是为了避免污染全局范围的人而制定的。

如何才能与“全球名称的懒惰用户”拥有同样的优势呢?通过利用use-指令,其中安全使命名空间中的名称可用于当前范围。

注意,在std通过正确使用use-指令而使作用域可用的命名空间(方法是将该指令放在#includes)污染全局命名空间。它只是使这些名字容易获得,并继续保护免受冲突。


查看完整回答
反对 回复 2019-06-24
  • 3 回答
  • 0 关注
  • 420 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信