C ++名称解析

时间:2013-01-03 10:09:57

标签: c++ namespaces using

我想知道C ++中的namespaceusing基本上我想知道差异并找出如何以最佳方式使用它。

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

  1. using namespace <namespace>
  2. using <namespace>::<what_to_use>
  3. <namespace>::<what_to_use> <use_it>
  4. 我想知道这些优点,特别是如果有一种或另一种方式涉及表现,如果只是语法和偏好问题,或者还有其他事情我没有考虑过这个。

5 个答案:

答案 0 :(得分:6)

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

其次是 using namespace declaration 。它只会在当前命名空间中显示指定的符号名称。优点是您不必每次都输入完全限定的名称。

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

显然,Second&amp;第三是更合适的。它们中的任何一个都没有性能差异。唯一的区别是您键入的字符数量。只需根据您的编码标准指定选择。

修改
正如@Jerry指出的那样,将声明与ADL(基于参数的查找)结合使用可能会产生不良影响 您可以在我的一个答案中找到详细解释:

<强> Detailed explanation on how Koenig lookup works with namespaces and why its a good thing?

根据该条,
为何批评Koenig算法?

答案 1 :(得分:4)

有一种(诚然,有些不常见)的情况,您使用的表单确实可以产生影响,而您想要使用的表单 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);
}

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

这会对性能产生影响 - 如果他们专门为他们的类型编写了一个交换,你通常可以期待它,因为通过这样做,他们可以提供更好的性能。这意味着明确指定std::swap可能有效,但可能会导致性能下降。

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

另一次,我发现使用声明/指令很有用的是命名空间真正深层嵌套的时候。 Boost(对于一个明显的例子)有一些名称,如果您每次都使用完全限定名称,那么这些名称对于方便使用来说太长了。对于(现在,幸运的是,大多数已经过时)Boost Lambda库来说尤其如此,你使用像_1这样的占位符,它最终会像boost::lambda::placeholders::_1那样(但我会从记忆中走出来)如果你坚持使用完全限定的名字,那么这可能至少部分是错误的。这首先打败了使用lambda库的大部分目的。

答案 2 :(得分:2)

没有任何表现上的提升或惩罚。所有调用和变量都在编译时解析。

三者之间的选择有点主观。是的,using namespace <ns>;有时不赞成污染全局命名空间,我认为可以安全地用于小文件。

我倾向于使用第二个用于测试目的,我预计会发生冲突,但之后我会将其删除。这可能会变得更加混乱,因为您最终可能会得到合格和不合格名称的组合:

vector<std::string> x;

因为您的顶部有一个using std::vector;,而不是using std::string;

我喜欢第三个。

答案 3 :(得分:1)

对代码的性能没有任何影响,这纯粹是编译时的事情。它(理论上)可能会对编译时间产生一些影响,但我怀疑它会达到可衡量的比例。

在头文件中肯定要避免

using namespace std(或任何其他名称空间),头文件可以包含在任何地方,并在其中引入符号可能会导致含糊不清。

通常,存在名称空间以避免名称冲突,using namespace会破坏此目的。 using the_namespace::some_id也是如此,程度较低。你的问题没有确切的答案,但我通常遵循这些规则:

  1. 从不using namespace放入头文件中。
  2. 避免使用using namespaceusing,除非它可以节省大量的输入内容。必要时使用命名空间别名(即namespace abbrv = some_really::long_and::nested_namespace;)。
  3. 尝试限制using的范围:您可以将其放入函数和块以及命名空间范围。也就是说,如果.cpp文件中有日志记录功能,请将using std::cout;using std::endl;(或者您使用的任何内容)放入函数体中,而不是放入文件范围。

答案 4 :(得分:0)

主要原因是它可能导致歧义(对于编译器和人类读者而言),它也可能减慢编译本身的速度(但这不是第一件大问题)