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

标签 c++ linux macos operator-keyword rvalue

这个简单的程序(在 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

第一个将打印一个十六进制地址,第二个将打印“Hello”。这是正确的行为,因为运算符 <<解析为两个不同的东西(C++03 中没有右值引用,所以你去吧)。

现在,在 OS X 上尝试同样的事情:


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

(这正确地产生了十六进制输出。)


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

(糟糕...仍然是十六进制输出...我们处于 C++11x 模式,但可能没有使用正确的 header ?)


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

> 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 构建问题。对于那些感兴趣的人,它在 C++03 和 C++11 中产生不同结果的原因在下面的一个答案中突出显示。

最佳答案

首先,预期的行为差异是因为 operator<<(std::ostream&, const char*)重载(它实际上是一个函数模板特化,但现在没关系)有一个类型为 std::ostream& 的参数并且左值引用只能绑定(bind)到左值,在您的示例中,流是右值,因此无法使用重载。在 C++03 中,这意味着唯一可行的重载是 std::ostream::operator<<(const void*)成员函数,因为成员函数可以在右值对象上调用,所以字符串写成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,因此没有 operator<<右值流的重载。使用 -std=c++0x告诉 Clang 支持 C++11 语言特性(例如右值引用),但并没有神奇地使 GCC 4.2 的库增长 C++11 代码,当 GCC 4.2 发布时,标准委员会甚至都没有注意到这些代码释放。 Apple 没有发布非史前的 libstdc++,而是编写了自己的标准库实现来配合 LLVM 和 Clang 项目。使用 -stdlib=libc++告诉 clang 使用 libc++ 标准库实现而不是古老的 libstdc++。由于 libc++ 是最近编写的,它有 operator<<右值引用的重载。

关于c++ - 在 OS X 上,简单的 C++ 程序会给出不正确的结果(这是命令行选项 'c++03' 与 'c++11' 的结果),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14149835/

相关文章:

c++ - 多个复制构造函数的编译器警告

c++ - CMake : Undefined reference to function

c++ - 我不明白 [dcl.enum]/4 与下面突出显示的 "enclosing enum specififer"相关的内容

macos - 您如何使用 Swift 在 Cocoa 应用程序的 View 之间导航?

macos - 更改激活策略 : from startup

c++ - 有没有办法找出第二个事件将在 MFC 中发生

c++ - 以编程方式从父级的子进程中捕获打印,这样它们就不会转到标准输出

linux - 在 GDB (Centos 6) 中查找该地址的值

linux - 在 amazon linux AMI 中安装 phpmyadmin 时遇到问题

macos - 如何在 Mac OSX 10.6 上安装 Perl DateTime 模块