相同的代码在Mac上正确,在Linux上不正确

时间:2017-10-31 01:15:39

标签: c++ linux macos

我遇到了一个问题,它引发了我一个循环(没有双关语意)。我试图说明重载运算符如何能够提高代码的可读性。为了做到这一点,我写了一个名为' cow' (没有特殊意义)。当我在Mac上编译代码时,它会干净地编译并按预期执行。

在Linux机器上编译的完全相同的代码(Ubuntu)也可以干净地编译,但执行时结果不正确。

在某个地方,我必须遗漏一些明显的东西,但我没有看到它。

以下是代码:

#include <iostream>
#include <sstream>
using namespace std;

class cow {
public:
    cow();
    cow(int i);
    int add(int a);
    int add(string str);
    int get() const;
private:
    int i;
};

cow::cow() {
    i = 0;
}

cow::cow(int j) {
    i = j;
}

int cow::add(string str) {
    stringstream s;
    int num;
    s << str;
    s >> num;

    return i += num;
}

int cow::add(int a) {
    return i += a;
}

int cow::get() const {
    return i;
}

int main() {
    cow i(15);
    cout << i.get() << " : " << i.add(15) << " : " << i.add("-15.0");
    return 0;
}

编译(g++ -Wall -o cow cow.cpp)不会产生任何警告,也不会产生错误,并创建可执行文件。

在Linux机器上执行程序会产生:

$ ./cow
15 : 15 : 0

在Mac上执行程序会产生:

$ ./cow
15 : 30 : 15

Mac上的C ++编译器是:

$ g++ --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.0.0 (clang-900.0.38)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

Linux机顶盒上的C ++编译器是:

$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

对于导致此行为的原因提出任何建议表示赞赏,以及在Linux机器上修复它的方法!

谢谢,

基斯

2 个答案:

答案 0 :(得分:2)

您在此行中遇到了未定义的行为:

cout << i.get() << " : " << i.add(15) << " : " << i.add("-15.0");

由编译器决定评估i.get ()i.add(15)i.add("-15.0")的顺序 - 除非评估其中一个会改变,否则它通常不会成为问题另一个的输出(这里就是这种情况 - i更改)。

当您使用不同的编译器(Linux上的g ++,Mac上的clang)时,每个编译器都会以不同的顺序进行评估。

答案 1 :(得分:2)

您将获得未定义的行为,因为您在一个表达式中多次更改了实例的状态。根据C ++标准,您在此行中调用了i

 cout << i.get() << " : " << i.add(15) << " : " << i.add("-15.0");

可以按任何顺序执行。 只是你的运气,Mac的编译器会按照您的预期执行从左到右的调用。 要获得可靠的结果,您应该按顺序评估这些调用,例如:

auto a1 = i.get();
auto a2 = i.add(15);
auto a3 = i.add("-15.0);
cout << a1 << " : " << a2 << " : " << a3;