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

为什么“使用命名空间std”被认为是不好的做法?

为什么“使用命名空间std”被认为是不好的做法?

料青山看我应如是 2019-05-20 15:45:32
我已经告诉别人,编写using namespace std代码是错误的,我应该用std::cout和std::cin直接代替。为什么被using namespace std认为是不好的做法?是低效还是冒着声明模糊变量(与名称std空间中的函数具有相同名称的变量)的风险?它会影响性能吗?
查看完整描述

7 回答

?
MM们

TA贡献1886条经验 获得超2个赞

这根本与性能无关。但请考虑一下:您正在使用两个名为Foo和Bar的库:

using namespace foo;using namespace bar;

一切正常,你可以毫无问题地Blah()从Foo和Quux()Bar 打电话。但有一天你升级到新版本的Foo 2.0,它现在提供了一个名为的功能Quux()。现在你遇到了冲突:Foo 2.0和Bar都导入Quux()了你的全局命名空间。这将需要一些努力来修复,特别是如果函数参数碰巧匹配。

如果你使用过foo::Blah()bar::Quux(),然后引进的foo::Quux()将是一个非事件。


查看完整回答
反对 回复 2019-05-20
?
吃鸡游戏

TA贡献1829条经验 获得超7个赞

Library Foo 2.0可以引入一个函数,Quux()这对于你的一些调用来说Quux()bar::Quux()你多年来调用的代码更明确地匹配。然后你的代码仍然编译,但它默默地调用错误的函数,并且知道神知道什么。这和事情一样糟糕。

请记住,在std命名空间有万吨标识符,其中许多都是常见的(想想listsortstringiterator,等),这是非常有可能出现在其他的代码了。

如果你认为这不太可能:在我给出这个答案大约半年之后,在Stack Overflow上有一个问题,其中几乎发生了这种情况(错误的函数被称为由于省略了std::前缀)。是另一个最近这样一个问题的例子。所以这是一个真正的问题。


这里还有一个数据点:很多年前,我也常常发现它必须为标准库中的所有内容添加前缀std::。然后我在一个项目中工作,在开始时决定using禁止指令和声明,除了函数范围。你猜怎么着?我们大部分时间都花了很长时间才习惯编写前缀,经过几周后,我们大多数人甚至同意它实际上使代码更具可读性。这是有原因的:你喜欢更短或更长的散文是主观的,但前缀客观上增加了代码的清晰度。不仅是编译器,而且您也更容易看到引用哪个标识符。

十年来,该项目增长了数百万行代码。由于这些讨论一次又一次地出现,我曾经很好奇这个(允许的)功能范围using实际上在项目中的使用频率。我找了它的来源,只发现了一两个地方使用它。对我而言,这表明,一旦尝试过,开发人员std::即使在允许使用指令的情况下,即使每100kLoC使用指令也不会发现痛苦。


底线:明确地为所有内容添加前缀不会造成任何伤害,很少习惯,并具有客观优势。特别是,它使编码器和人类读者更容易理解代码 - 这应该是编写代码时的主要目标。


查看完整回答
反对 回复 2019-05-20
?
蓝山帝景

TA贡献1843条经验 获得超7个赞

放入using namespace类的头文件的问题在于它强制任何想要使用您的类(通过包含头文件)的人也可以“使用”(即看到所有内容)这些其他命名空间。

但是,您可以随意在(私有)* .cpp文件中放置using语句。


请注意,有些人不同意我这样的说法“感觉自由” - 因为虽然cpp文件中的using语句比标题中的更好(因为它不会影响包含头文件的人),但他们认为它仍然存在没有良好的(因为这取决于它的代码可以使课堂更加难以维持的实现)。这个FAQ主题说,

using-directive存在于遗留C ++代码中,并且可以简化向命名空间的转换,但您可能不应该定期使用它,至少不能在新的C ++代码中使用它。

FAQ提出两种选择:

  • 使用声明:

    using std::cout; // a using-declaration lets you use cout without qualificationcout << "Values:";
  • 只需输入std ::

    std::cout << "Values:";


查看完整回答
反对 回复 2019-05-20
?
潇湘沐

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

不应该在全局范围内使用using指令,尤其是在头文件中。但是,即使在头文件中也存在适当的情况:

template <typename FloatType> inlineFloatType compute_something(FloatType x){
    using namespace std; //no problem since scope is limited
    return exp(x) * (sin(x) - cos(x * 2) + sin(x * 3) - cos(x * 4));}

这比显式限定(std::sinstd::cos...)更好,因为它更短并且能够使用用户定义的浮点类型(通过Argument Dependent Lookup)。


查看完整回答
反对 回复 2019-05-20
  • 7 回答
  • 0 关注
  • 1483 浏览

添加回答

举报

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