gcc / c ++ 11:优化级别改变操作的结果

时间:2015-10-04 10:39:05

标签: c++11 gcc optimization

在C ++类中,我重载了operator-()。当我使用-O0进行编译时,它的行为与预期的一样,但是当我使用至少-O1进行编译时,尽管没有生成错误,但调用operator-()的结果是错误的。

我不是C ++专家,但在下面的代码片段中对我来说似乎并不奇怪。 与我在这个网站上遇到的其他情况不同,我没有内联asm,我没有调用库,等等。代码中包含了所有内容。

以下是我使用的gcc版本:

g++ (GCC) 4.9.3
Copyright © 2015 Free Software Foundation, Inc.
Ce logiciel est libre; voir les sources pour les conditions de copie.
Il n'y a PAS GARANTIE; ni implicite pour le MARCHANDAGE ou pour un BUT PARTICULIER.

g++ (GCC) 5.2.0
Copyright © 2015 Free Software Foundation, Inc.
Ce logiciel est libre; voir les sources pour les conditions de copie.
Il n'y a PAS GARANTIE; ni implicite pour le MARCHANDAGE ou pour un BUT PARTICULIER.

编译命令:

OK : g++ --std=c++11 -O0 -o test test.cpp
KO : g++ --std=c++11 -O1 -o test test.cpp

我得到了预期的警告:

test.cpp: In member function ‘A& A::operator-(const A&)’:
test.cpp:23:5: attention : reference to local variable ‘tmp’ returned 
[-Wreturn-local-addr]
   A tmp(*this);
     ^

添加-Wno-return-local-addr不会改变任何内容,因为它只是删除了警告

以下是重现问题的代码段:

#include <iostream>

using namespace std;

class A {
public:
  double val;

  A(int _val) : val(_val) {}

  A() : val(0.0) {}

  A(const A&) = default;
  A(A&&) = default;
  A& operator=(const A&) = default;
  A& operator=(A&&) = default;

  A& operator-(const A& other) {
    A tmp(*this);
    tmp.val -= other.val;

    return tmp;
  }

};

int main() {

  A a(3);
  A b(2);

  A c = b - a;

  cout << c.val << endl;

  return 0;
}

如果我添加一个运算符 - =()

  A& operator-=(const A& other) {
    this->val -= other.val;

    return *this;
  }

并更改为main:

A c = b - a;

A c(b);
c -= a;

无论-Ox选项如何,我的工作都很完美。

我怀疑从operator-()返回对局部变量的引用是问题的根源(尽管c ++ 11的RVO功能?)。 我没有得到的是为什么优化水平会产生这样的影响?

毕竟,mys代码有问题吗?

1 个答案:

答案 0 :(得分:3)

您的operator-()正在返回对本地变量的引用。这会导致调用者在使用该引用时显示未定义的行为。

传统上,operator-()按值返回对象,而不是按引用返回。这是有道理的,因为c = a - b通常会使ab保持不变,并给出c它们之间的差异(无论如何定义)。