在OS X上,简单的C ++程序给出了不正确的结果(这是命令行选项“c ++ 03”与“c ++ 11”的结果)。

这个简单的程序(在Linux上编译时)将根据是否使用-std=c++0x编译,正确地给出两个不同的答案。

问题:我无法在OS X(Mountain Lion,10.8 SDK)上重现相同的内容。 我错过了什么?

 #include <iostream> #include <sstream> class Thing : public std::ostringstream { public: Thing() : std::ostringstream() {} virtual ~Thing() { std::cerr << str(); } }; int main(int argc, const char * argv[]) { Thing() << "Hello" << std::endl; return 0; } 

要明白我的意思,请执行以下操作(首先在Linux上查看它应该如何工作):

 > g++ main.cpp > ./a.out 0x401471 

 > g++ -std=c++0x main.cpp > ./a.out Hello 

第一个将打印一个hex地址,第二个将打印“你好”。 这是正确的行为,因为运算符<<解决了两个不同的事情(在C ++ 03中没有右引用,所以你去)。

现在,在OS X上尝试相同的东西:


 > xcrun c++ main.cpp > ./a.out 0x10840dd88 

(这正确地产生hex输出。)


 > xcrun c++ -std=c++0x main.cpp > ./a.out 0x10840dd88 

(糟糕…仍然是hex输出…我们在C ++ 11x模式,但也许正确的标题没有被使用?)


注意:编译器的版本在这里:

 > xcrun c++ --version Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn) Target: x86_64-apple-darwin12.2.0 Thread model: posix 

注意:这本身不是C ++问题,而是OS X构build问题。 对于那些有兴趣的人来说,它在C ++ 03和C ++ 11中产生不同结果的原因在下面的一个答案中突出显示。

Solutions Collecting From Web of "在OS X上,简单的C ++程序给出了不正确的结果(这是命令行选项“c ++ 03”与“c ++ 11”的结果)。"

首先,预期的行为差异是因为operator<<(std::ostream&, const char*)重载(它实际上是一个函数模板特化,但现在从来不是)具有类型std::ostream&的参数和一个左值引用只能绑定到一个左值,在你的例子中,流是一个右值,所以过载不能被使用。 在C ++ 03中,意味着唯一可行的重载是std::ostream::operator<<(const void*)成员函数,因为可以在rvalue对象上调用成员函数,所以字符串被写成void*地址以十六进制表示。 在C ++ 11中有一个新的operator<<(std::ostream&&, const T&)函数模板,它允许写入右值流,并转发给operator<<(std::ostream&, const char*)重载,所以该字符串是输出而不是一个十六进制地址。

在GNU / Linux上,你大概会使用一个相当新的GCC版本,它在编译器(g ++)和标准库(libstdc ++)中都有相当好的C ++ 11支持,所以它有operator<<(std::ostream&&, const T&)重载和一切正常工作。

在OS X上,您可能使用Clang和GCC的标准库libstdc ++。 Xcode默认使用GCC的古老版本(4.2),而GCC 4.2的标准库不支持C ++ 11,所以没有rvalue流的operator<< overload。 使用-std=c++0x告诉Clang支持C ++ 11语言特性(比如右值引用),但是不会奇迹般地让GCC 4.2的库增长C ++ 11代码甚至不是一个闪烁GCC 4.2发布时的标准委员会的眼睛。 而不是发布一个非史前的libstdc ++苹果公司,而是写了他们自己的标准库实现去与LLVM和Clang项目。 使用-stdlib=libc++告诉clang使用libc ++标准库实现而不是古老的libstdc ++。 由于libc ++是最近编写的,它有operator<< rvalue引用的重载。

这似乎是叮当使用libstdc ++默认,而不是libc ++的问题。 像这样编译: clang++ -std=c++0x -stdlib=libc++ test.cpp产生预期的输出。