2015-05-29 191 views
1

我是相當新的節目在C++中,我想知道的東西:C++運算符重載返回指針

每當我看到操作符重載在C++中,它的完成這樣的:

#ifndef STONE_H 
#define STONE_H 

class Stone { 
    private: 
    int weight; 

    public: 
    ....... 

    Stone operator+(const Stone& s) { 
     Stone stone; 
     stone.weight = this->weight + s.weight; 
     return stone; 
    } 

    ....... 
} 


#endif 

但當「 +「運算符被調用,它創建一個對象」stone「,並返回這個副本。處理巨大的物體時,這對性能不利?

那豈不是更好地使用這個動態內存,如下面的例子:

Stone * operator+(const Stone& s) { 
    Stone * stone = new Stone; 
    stone->weight = this->weight + s.weight; 
    return stone; 
} 

還是我看到這錯了嗎?

在此先感謝

+2

看到這一點:http://stackoverflow.com/questions/ 12953127/what-are-copy-elision-and-return-value-optimization – NathanOliver

+3

誰會釋放這些對象?這裏'a + b + c'? – StoryTeller

+1

總是使用delete刪除對象(有一個二元運算符,您可能會遇到內存泄漏)。第一種方法很好(看看返回值優化) –

回答

2

試圖講道理是沒有估計性能的特別準確的方法:實際上你需要一個程序寫入措施一個實現是否比另一種更好。

有很多方法根本不會發生副本;指定的返回值優化(NRVO)和移動分配在這裏是相關的想法。

即使您決定要做類似於您的建議的事情,也不應該像現在這樣執行它,因爲它具有錯誤的語義:您有operator+返回一個指向事物的指針而不是事情。另外,使用指針(尤其是裸指針)的工作是有風險的,因爲它給了你更多犯錯的機會。

如果你想要沿着這些線實現某些東西,你需要將指針語義包裝在一個提供值語義的類中。

0

原來在當前標準中,這是一個有點不同:

#include <iostream> 

class big { 
    int* v; // Demonstration purposes. A smart pointer or a standard container would be better. 
    public: 
    big& operator+=(big& o) { 
    for (int i=0;i<1000;++i) { 
     v[i] += o.v[i]; 
    } 
    return *this; 
    } 

    big(int val = 0) 
     : v{new int[1000]} // We're using RAII to prevent resource leaking. 
    { 
    std::cout << "a construction.\n"; 
    for (int i=0;i<1000;++i) { 
     v[i] = val; 
    } 
    } 

    // Copy constructor 
    big(big& o) 
     : v{new int[1000]} 
    { 
    std::cout << "a copy construction.\n"; 
    for (int i=0;i<1000;++i) { 
     v[i] = o.v[i]; 
    } 
    } 

    // Move assignment 
    big& operator=(big&& o) { 
    std::cout << "a move assignment.\n"; 
    if (v) delete[] v; 
    v = o.v; 
    o.v = nullptr; 
    } 

    // Move constructor 
    big (big&& o) { 
    std::cout << "a move construction.\n"; 
    v = o.v; 
    o.v = nullptr; 
    } 

    ~big() { 
    if (v) delete[] v; 
    } 
}; 

// a will be move-constructed if using a temporary, or copy-contructed if not. 
// The result will always be passed by a cheap move 
big operator+(big a, big& b) { 
    return std::move(a += b); 
} 

int main() { 
    big a{1}; 
    big b{2}; 
    big c{3}; 

    big d = a+b+c; 
} 

輸出:(添加評論)

a construction. // Constructed a 
a construction. // Constructed b 
a construction. // Constructed c 
a copy construction. // a+b <- a copied into parameter "a" of operator+. b is passed by reference. 
a move construction. // The temporary from the operation above, moved into parameter "a" of operator+. c is passed by reference. 
a move construction. // d is move constructed from the temporary generated by a+b+c.