【问题标题】:Using namespace std vs other alternatives [duplicate]使用命名空间 std 与其他替代方案 [重复]
【发布时间】:2014-12-06 19:15:27
【问题描述】:
using namespace std;

到目前为止,在我的计算机科学课程中,这就是我们被告知要做的所有事情。不仅如此,这也是我们被允许做的所有事情,否则我们的代码会受到惩罚。我了解到,通过查看在线发布的代码,您可以使用 ::std 或 std:: 来完成同样的事情。

我的问题一般是为什么?显然,为了学习者和简单性,使用全局声明更简单,但有什么缺点呢?在现实世界的应用程序中期待 ::std 是否更现实?我想补充一点,使用声明背后的逻辑/概念是什么?在我的课程中,这些都没有解释过,我想更好地掌握它。

作为一个普遍的问题:如果我没有学过这些内容、向量、模板、类或错误处理,我是否会错过很多基本的 C++ 功能?

提前致谢!

【问题讨论】:

  • 我建议花一点时间阅读this question and its various posted answersusing namespace std; 无辜地坐在某个翻译单元中的一个杰出示例导致了意想不到的后果can be seen here。值得一读。
  • 谢谢,我去看看!我试图事先找到一些例子,但其中很多都像是“是的,它有时会导致问题。”没有证据。
  • 不分青红皂白使用using namespace ...是恕我直言不好的做法,这可能会导致许多微妙的、难以找到的错误。它绕过了将名称空间引入语言的全部原因。话虽这么说,当using namespace ... 的范围是restricted(通过命名空间或本地范围)时,它有适当的用途。即使std 命名空间非常大并且包含许多 常用符号,所以我总是 避免使用using namespace std另见: The C++ FAQ
  • 但我应该补充一点,按照你的 CS 教授在课堂上告诉你的做,但不要接受任何人告诉你的任何事情。学习最佳实践是一个持续的过程,多年来你会从许多不同的人那里学到它们。 (即便如此,人们仍然会为其中一些争论,呵呵)。
  • 教授教做什么做什么,惩罚你不这样做,不说为什么,这让我很不高兴。 using 关键字可能会导致很多问题;我尽量不使用它(是的,在大多数情况下意味着非常冗长的代码)。

标签: c++


【解决方案1】:

我想说的是,一般来说,您不会在全局范围内声明使用 std。我想如果您正在制作一个简单的应用程序,那就足够了。但是,当您在大型组织中工作时,您通常会使用不同的命名空间,并且这些命名空间可能具有重叠的对象。如果您在 std 和您创建的命名空间中有一个函数,然后调用“使用命名空间 std”和“使用命名空间 yournamespace”,则在调用该函数时会得到不需要的结果。当您在每个调用前加上命名空间时,它会更清晰,不会出现重叠问题。

【讨论】:

  • 如果您仍然希望 ADL 正常工作,则使用命名空间为每个调用添加前缀不是一种可行的方法。给定using namespace std; template <typename T> void Foo(T &a, T &b) { swap(a, b); },您如何将调用更改为swap 以继续允许`namespace N { struct S { }; void swap(S &, S &); },其中Foo<N::S> 应该调用N::swap 而不是std::swap
  • 为此,您确实需要using,但您可以将其限制为您想要的那些功能,而不是所有namespace std
  • @user3857017 标准库将几乎所有内容都直接放入std。 (标准库的特定实现确实在内部使用了额外的命名空间,但这些是特定于实现的细节,通常不打算由程序直接使用。)文件访问、线程、容器,它们都是std 的一部分命名空间。它可能有不同的组织方式,文件访问使用单独的命名空间,容器类型使用单独的命名空间等,其他一些库确实采用这种方法,但标准库没有。
  • @user3857017 您可能已经看到了类成员访问,它使用与命名空间成员访问相同的语法。给定A::B::CA 可以是命名空间或类,如果是命名空间,B 可以是命名空间或类。仅从语法无法判断,您必须查找名称。是的,在某种程度上,像这样的类可以用作命名空间,但不完全是。
  • @user3857017 啊,好的。简短的回答:命名空间只是对名称进行分组以防止冲突的一种方式。如果你有一个函数f() 和另一个函数f(),在没有命名空间的语言中,你只是有一个冲突,如果不重命名其中一个函数就无法解决。在确实具有命名空间的语言中,定义函数的人可以选择将其放在单独的命名空间中,如果这两个函数不在同一个命名空间中,则不会发生冲突,这些函数可以共存。如何使用命名空间取决于定义函数的人。
【解决方案2】:

一般为什么?

命名事物是软件开发中比较困难的方面之一。初学者根本不知道他们的名字选择以后会如何产生歧义。

特别是,我们的软件行话通常对某些问题有首选术语。这些偏好可能导致不相关的类实例被开发为具有相似含义的相同(或相似)符号。

我经常使用的一些符号包括 init()、exec()、load()、store(),并且我在很多地方都使用了 timeStampGet()。我也使用 open()、close()、send()/recv() 或 write()/read()。

因此,我可以在 3 个名称空间中的每一个中重命名 init(),并在其中添加了 5 个对象,但指定我想要的对象要简单得多。
我在 2 个名称空间和 12 个对象中找到了 exec()。我使用了 3 种不同的 timeStampGet() 方法。无论是命名空间、函数还是类方法,这些符号对我来说都很有意义。

此外,我发现 5 char "std::" namespace-as-prefix 完全自然,并且比全局“using namespace std”更可取。我想这需要练习。

还有一个项目 - 任何较大的名称空间或类名变得令人厌烦的地方,我有时会添加一个 typedef 短名称...这里是生产代码中的一些示例:

typedef ALARM_HISTORY   ALM_HST;
typedef MONITOR_ITEM    MI
typedef BACKUP_CONTROL  BC;

在一个团队中,我们同意使用定义明确的“完整”名称,但有时会因为篇幅太长而令人厌烦。在项目的后期,我们一致认为 typedef(用于短类或命名空间名称)可以在简单且不会造成混淆的情况下使用。

【讨论】:

  • 这有点超出我的想象,但我想我至少在我的问题方面得到了前提,谢谢!
【解决方案3】:

这确实是您可以在啤酒中讨论数小时的事情之一,但仍然没有每个人都满意的答案。

如果您几乎总是使用std:: 功能,那么在文件开头添加using namespace std; 并不是一个坏主意。另一方面,如果您使用来自多个命名空间的东西(例如,使用llvm:: 编写编译器并同时使用std::,则可能会混淆哪些部分是llvm 的一部分,哪些部分是@ 987654326@ - 所以在我的编译器项目中,我没有带有using namespace ...; 的单个文件 - 相反,我根据需要写出llvm::std::。有几个函数(可能是不明智的)称为Type(),有些地方使用something->Type()->Type() 来获取我需要的类型……是的,它有时甚至让我有点困惑……

我也有很多类似Constants::ConstDeclToken::RightParen的东西,这样我可以快速看到“什么是什么”。所有这些都可以变得更短和“更简单”,但我更愿意在大多数情况下查看事物的归属。

更详细有助于更轻松地查看事物所属的位置 - 但它有助于更​​多打字和更多阅读,所以这是一种平衡。

【讨论】:

  • I don't have a single file with using namespace ...; +1;我知道 许多 开发人员(包括我自己)喜欢这种方式。
  • @Qix 明确一点,当我快速编写一些代码以显示“这是如何完成的”时(例如这里),我可能会使用using namespace std;。但对于我的编译器项目和其他更大的项目,我不这样做。
  • 当然,这是明智的。
【解决方案4】:

我个人讨厌“使用”声明。对我来说,它们使代码不可读,并且您破坏了命名空间。我已经做了 20 年的维护程序员,我讨厌任何使代码更难阅读的东西——在我看来,使用与抛出规范一样无用。

6 个月 - 一年 - 10 年后什么更易读

UDP::Socket sock
sock.send(data)
TCP::Socket sock2
sock2.send(data)

using UDP;
using TCP;
sock.send(data)
sock2.end(data)

我也不喜欢命名空间别名

using namespace po = boost::program_options; 

现在你正在让下一个程序员更加努力地工作,通过额外的间接级别查找 po 与 boost::program_options 的比较。

的那些可怕的 typedef 也是如此
typedef long QUADWORD;

四字的大小是多少 - 一个长的 4 个字节有多长?在我的操作系统上 8 个字节可能是 17 个字节

我最后的看法是,如果你不会打字,那就不要成为程序员 - 保存的击键!= 良好的可维护代码

【讨论】:

    猜你喜欢
    • 2015-10-05
    • 2012-09-09
    • 1970-01-01
    • 2017-08-06
    • 2016-01-11
    • 2018-10-28
    • 1970-01-01
    • 2014-07-08
    • 2011-07-24
    相关资源
    最近更新 更多