2015-10-04 63 views
1

在C++類中,我重載了operator-()。當我用-O0進行編譯時,它的行爲和預期的一樣,但是當我用至少-O1編譯時,儘管沒有生成錯誤,但調用operator-()的結果是錯誤的。gcc/C++ 11:優化級別更改操作結果

我不是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回本地-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; 
    } 

和變化在主:

A c = b - a; 

A c(b); 
c -= a; 

無論-Ox選項如何,我的工作都很完美。

我懷疑從operator-()返回一個局部變量的引用是問題的根源(儘管C++ 11的RVO功能?)。 我沒有得到的是爲什麼優化的水平有這樣的效果?

畢竟,mys代碼有什麼問題嗎?

+4

請問翻譯後的標題?這將緩解人們尋找郵件的願望。 – sergico

+2

你正在返回一個懸而未決的參考,因此,它是UB –

+1

閱讀關於如何編寫操作符的建議:http://stackoverflow.com/questions/11726171/numeric-vector-operator-overload-rvalue-reference-parameter – user2672165

回答

3

您的operator-()正在返回對局部變量的引用。這會導致調用者在使用該引用時顯示未定義的行爲。

傳統上,operator-()按值返回對象,而不是通過引用。這是有道理的,因爲c = a - b通常保留ab不變,並給出c它們之間的差異(但是已定義)。