在C ++中使用标准C函数时,是否需要“std ::”前缀?

时间:2015-04-27 13:49:25

标签: c++ c

在C ++中使用标准C函数时,我们应该为每个函数添加std::吗?

例如

(文件名:std.C):

#include <cstdio>

int main() {
  std::printf("hello\n");
  printf("hello\n");
}

可以使用以下命令编译此文件:

g++ -Wall -Werror -std=c++11 std.C

没有任何错误。

我的问题是:

  1. 在C ++中使用时,我们是否应始终将std::置于所有标准C库函数之前?
  2. <stdio.h><cstdio>等标题文件之间的主要区别是什么?

3 个答案:

答案 0 :(得分:9)

  

C ++库包含与C语言相同的定义   库中组织了与头文件相同的结构,用   以下差异:

     
      
  • 每个头文件与C语言版本具有相同的名称,但前缀为“c”且没有扩展名。例如,C ++等价物   对于C语言头文件<stdlib.h><cstdlib>
  •   
  • 库的每个元素都在std命名空间中定义。
  •   
     

然而,为了与C兼容,传统的标题名称   name.h(如stdlib.h)也提供了相同的定义   尽管在C ++中不推荐使用它,但在全局命名空间中。

source

std::调用的std::printf()部分是在标准库中使用名称的标准方法,因此,我建议使用它。

答案 1 :(得分:3)

C ++标准库包含C标准库(稍作调整)。

每个名为<foo.h>的C标头都有一个对应的C ++标头<cfoo>。例如,C ++标头<cstdio>对应于C标头<stdio.h>

引用2011 ISO C ++标准,17.6.1.2 [header]第4段:

  

然而,在C ++标准库中,声明(除了   在C)中定义为宏的名称在命名空间范围内   名称空间 std 的(3.3.6)。这些名称是否未指明   首先在全局命名空间范围内声明,然后是   通过显式 using-declarations (7.3.3)注入名称空间 std

因此,#include <cstdio> printf函数肯定可以称为std::printf,而可选可以显示为全局命名空间中的printf。 (此选项取决于实现,而不是程序员。)

当然,您可以在printf的范围内将其称为using namespace std

在我看来,这是不幸的;它似乎是为了方便实施者而不是程序员。最安全的做法是假设在printf命名空间中std仅声明 。如果您使用#include <cstdio>然后在全局命名空间中引用printf,那么您的代码今天可能会编译而无法在不同的实现上进行编译。

相反,作为已弃用的功能,C ++标准库还包含带有原始名称的C标准标头,例如<stdio.h>。引用标准,第D.5节[depr.c.header]:

  

每个C标头,每个标头都有 name.h 形式的名称,   表现就像每个名称放在标准库名称空间中一样   相应的 cname 标头位于全局命名空间内   范围。未指定是否首先声明这些名称或   在命名空间 std 的命名空间范围(3.3.6)中定义   然后通过显式注入全局命名空间范围    using-declarations (7.3.3)。

所以给定#include <stdio.h>,名称printf 肯定在全局命名空间中可见,而可选(同样,这是实现的选项) ,而不是你的)std::printf可见。

答案 2 :(得分:1)

  1. std 是命名空间,使用 :: (在 std 之后)显式使用命名空间std的功能。现在,假设您创建自己的命名空间,并且您在其中创建的一些函数与std命名空间中的函数具有相同的名称。这可能是个问题,但是通过使用std :: func1和YourNameSpace :: func1可以防止出现这个问题。
  2. Look in here。谢谢@karma_geek