C++ 重新定义变量,全局命名空间被污染,我不知道为什么

C++ redefinition of variable, global namespace polluted and I don't know why

所以我认为我做了一些非常愚蠢的事情,我就是想不通。下面的程序让我很痛苦:

#include <iostream>
int time = 0;
int main(int argc, char **argv) {
    std::cout << "hi" << std::endl;
    return 0;
}

我的编译字符串是:clang++ -std=c++1y --verbose -stdlib=libc++ main.cpp -o main。重新定义错误是 /usr/include/time.h:116:8: note: previous definition is here 并且 --verbose 将此显示为包含路径顺序:

Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.1.0
Thread model: posix
 "/Library/Developer/CommandLineTools/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.10.0 -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -main-file-name main.cpp -mrelocation-model pic -pic-level 2 -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 241.9 -v -resource-dir /Library/Developer/CommandLineTools/usr/bin/../lib/clang/6.0 -stdlib=libc++ -std=c++1y -fdeprecated-macro -fdebug-compilation-dir /Users/aliak/dev/atom/sim -ferror-limit 19 -fmessage-length 0 -stack-protector 1 -mstackrealign -fblocks -fobjc-runtime=macosx-10.10.0 -fencode-extended-block-signature -fcxx-exceptions -fexceptions -fdiagnostics-show-option -vectorize-slp -o /var/folders/r_/pmd7rtcd4h35dqsf496nyzsh0000gn/T/main-d500bd.o -x c++ /Users/aliak/dev/atom/sim/main.cpp
clang -cc1 version 6.0 based upon LLVM 3.5svn default target x86_64-apple-darwin14.1.0
ignoring nonexistent directory "/usr/include/c++/v1"
#include "..." search starts here:
#include <...> search starts here:
 /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1
 /usr/local/include
 /Library/Developer/CommandLineTools/usr/bin/../lib/clang/6.0/include
 /Library/Developer/CommandLineTools/usr/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)

我只是想不通出了什么问题。如果我在命令行参数中添加 -nostdinc++ 到 clang,然后删除 iostream include,但保留时间 var,一切正常。我猜这意味着 iostream 包括 time.h。但我很困惑,它不应该包括 ctime 而不是 time.h,这会将所有内容都包装在 std 命名空间中吗?

我试过删除 xcode 并重新安装。

更新:

Mats 的评论让我做了更多的窥探。因此,将 -H 传递给 clang++ 会打印出 header 树。事实证明 pthread.h 是实际包含 time.h 的那个。但是ctime其实也包含了time.h。这似乎符合标准,因为:"In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace std. It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations"

time() 是标准 C 中的一个函数,这意味着它位于命名空间之外,因此 "old" C 代码可以用 C++ 编译器编译,而不会抛出很多 using namespace std无处不在。

当您包含 <iostream> 时,header time.h 显然也包含在内,这就是为什么您会得到对它的引用。

要么不使用该名称,要么添加 namespace MyName { int time; };,然后在您要引用变量时使用 MyName::time

[我不知道确切的位置,但我相信 C++ 标准声明“现有的标准库函数可能存在也可能不存在于 std:: 命名空间之外,例如 <ctime> - <ctime> 的实际实现几乎肯定在某处包含常规 <time.h>。]

例如,在我的 linux 框上的 g++ 4.9.2 headers 中:

....
#pragma GCC system_header

#include <bits/c++config.h>
#include <time.h>

#ifndef _GLIBCXX_CTIME
#define _GLIBCXX_CTIME 1

 ...     
namespace std
{
  ...
  using ::time;
  ...
} // namespace

libcxx 中的那个看起来几乎相同。