C++名称解析

qri*_*kko 7 c++ namespaces using

我想知道一点关于namespaceusingC++基本上我想知道差异并弄清楚如何以最好的方式使用它.

我看到它有(至少)三种方法来解决一个类名,我不知道如何选择它们:

  1. using namespace <namespace>
  2. using <namespace>::<what_to_use>
  3. <namespace>::<what_to_use> <use_it>

我想知道优势,特别是如果有一种或另一种方式涉及性能,如果它只是语法和偏好的问题,或者是否有其他事情我没有考虑过这个.

Alo*_*ave 6

首先是using namespace指令,它带来当前命名空间中指定命名空间的所有符号名称,无论您是否需要/使用它们.当然不受欢迎.

其次是使用命名空间声明.它只会在当前命名空间中显示指定的符号名称.优点是您不必每次都输入完全限定的名称.

第三个是符号的完全限定名称.缺点是您必须在使用符号的任何位置键入完全限定名称.

显然,第二和第三是更合适的.它们中的任何一个都没有性能差异.唯一的区别是您输入的字符数量.简单地说,根据您的编码标准指定选择.

编辑:
正如@Jerry指出的那样,将声明与ADL(基于参数的查找)结合使用会导致不良影响.
你可以在我的一个答案中找到详细的解释:

关于Koenig查找如何与命名空间一起使用以及为什么它是一件好事的详细解释?

在该部分下,
为什么批评Koenig算法?


Jer*_*fin 5

有一种(诚然,有点不常见)情况,您使用的形式确实可以产生影响,而您想要使用的形式 using namespace foo,并且它最常应用于std命名空间(即,您在其中编写using namespace std;.

最明显的例子是您正在为用户定义类型编写排序。这可能应用于用户也定义了自己的类型swap

您陷入了这样一种情况:如果他们定义了交换,您想使用他们的交换,但如果他们没有定义交换,则使用 std::swap。std::swap如果您直接在代码中使用,那么std::swap即使该类型有自己定义的交换,您最终也会使用。相反,如果您直接专门为该类型指定交换,并且没有提供任何交换,则您的代码将无法编译。

为了解决这个问题,你可以这样做:

using namespace std;

template <class Iter>
void my_sort(Iter first, Iter last) {
    // ...
    if (*last < *first)
        swap(*first, *last);
}
Run Code Online (Sandbox Code Playgroud)

这将找到专门用于被比较类型的交换(即,swap在与该类型相同的命名空间中定义的交换),如果有一个交换(通过参数相关查找),并且std::swap如果没有为该类型定义交换(通过using namespace std;)。

这可能会对性能产生影响 - 如果他们专门为其类型编写了交换,您通常可以预期这是因为通过这样做,他们可以提供更好的性能。这意味着显式指定std::swap可能有效,但可能会导致性能较差。

否则,这几乎完全是一个方便性和可读性的问题——我最喜欢给出全名(例如,std::swap),除了上面这样的情况,其中(在我编写代码时)至少有两种可能性之一可能是首选,我想给编译器足够的余地来选择正确的。

我发现使用声明/指令有用的另一次是当名称空间嵌套得非常深时。Boost(举一个明显的例子)有一些名称,如果您每次都使用完全限定名称,那么这些名称将太长而无法方便使用。对于(现在,谢天谢地,大部分已经过时的)Boost Lambda 库尤其如此,您在其中使用了诸如 之类的占位符_1,最终结果会是这样的boost::lambda::placeholders::_1(但我是凭记忆写的,所以这可能至少部分是错误的)如果您坚持使用完全限定名称。这首先就违背了使用 lambda 库的大部分目的。

  • 但是,我想说,在这种情况下,您更愿意使用“using std::swap;” (2认同)