2013-10-19 63 views
0

我正在玩C++來提醒自己。所以我嘗試了運算符+重載返回引用。此動機是爲了避免不必要的對象複製。看看這個例子。我使用+創建了類String和串聯的字符串。這只是實驗,所以你會注意到一些醜陋的東西作爲公共屬性。從臨時對象重載operatora和表達式返回引用

這裏是代碼的相關部分。

String.hpp

#ifndef STRING_HPP_ 
#define STRING_HPP_ 

#include <iostream> 

using namespace std; 

#ifndef CPP11 
    typedef wchar_t unicode16; 
#else 
    typedef char16_t unicode16; 
#endif //CPP11 

class String { 

    unicode16 * value; 
    unsigned strLength; 

    void initEmpty() { 
     value = 0L; 
     strLength = 0; 
    } 

    static unsigned counter; 
public: 

    static String ** trash; 

    unsigned id; 

    String::String() : value(0L), strLength(0){ 
     id=counter++; 
     trash[id]=this; 
     cout << "Creating empty: " << id << "\n"; 
    } 

    String::String(const String &str); 

    String(const char *); 

    String(const unicode16 *); 

    unsigned length() const { 
     return strLength; 
    } 

    ~String() { 

     wcout << L"Deleting " << id << ": " << value << L"\n"; 
     trash[id]=0L; 
     delete value; 
    } 

    String & operator +(String &); 

    unicode16 * getValue() { 
     return value; 
    } 
}; 

#endif /* STRING_HPP_ */ 

String.cpp

#include "String.hpp" 
#include "../exception/IllegalArgumentException.h" 
#include <string.h> 


unsigned String::counter = 0; 

String ** String::trash = new String *[100](); 

String::String(const String & str) { 
    value = new unicode16[str.strLength + 1]; 
    strLength = str.strLength; 
    for(int i = 0; i < strLength ; i++) { 
     value[i] = str.value[i]; 
    } 
    value[strLength] = 0; 
    id = counter++;trash[id]=this; 
    wcout << L"Created (copy): " << id << ": " << value << L"\n"; 
} 

String::String(const char *charArray) { 
    if (charArray == 0L) { 
     throw IllegalArgumentException("Char array pointer is null"); 
    } 
    strLength = strlen(charArray); 
    value = new unicode16[strLength + 1]; 

    for (int i = 0; i < strLength; i++) { 
     value[i] = (unicode16)charArray[i]; 
    } 
    value[strLength] = 0; 
    id = counter++;trash[id]=this; 
    wcout << L"Created (char *): " << id << ": " << value << L"\n"; 
} 

String::String(const unicode16 *utfArray) { 
    if (utfArray == 0L) { 
     throw IllegalArgumentException("Unicode array pointer is null"); 
    } 
    strLength = wcslen(utfArray); 
    value = new unicode16[strLength + 1]; 

    for (int i = 0; i < strLength; i++) { 
     value[i] = utfArray[i]; 
    } 
    value[strLength] = 0; 
    id = counter++; 
    trash[id]=this; 
    wcout << L"Created (unicode): " << id << ": " << value << L"\n"; 
} 

String & String::operator +(String &str) { 
    unsigned newLength = length() + str.length(); 
    unicode16 * newArray = new unicode16[newLength + 1]; 
    wcscpy(newArray, value); 
    wcscpy(newArray + strLength, str.value); 

    String * strPointer = new String(); 
    strPointer->value = newArray; 
    strPointer->strLength = newLength; 

    String &result = *strPointer; 
    wcout << L"Empty loaded: " << result.id << ": " << result.value << L"\n"; 
    return result; 
} 

和主方法

#include "../string/string.hpp" 
#include <iostream> 

using namespace std; 



int metodica(void) { 
    String & please = String("Please"); 
    String meString = "me"; 
    String & me = meString; 
    String & delStrRef = String(" delete "); 

    String & result1 = please + delStrRef + me; 

    wcout << result1.getValue() << L"\n"; 
    delete &result1; 
    return 0; 
} 


int main(void) { 
    metodica(); 
    cout << "These are not deleted\n"; 
    for (int i = 0; i < 100; i++) { 
     if (String::trash[i] != 0L) { 
      wcout << String::trash[i]->getValue() << "\n"; 
     } 
    } 
} 

使用VS2010編譯器和鏈接在CDT執行此我得到以下輸出

創建(字符*):0:請

創建(字符*):1:我

創建(字符*):2:刪除

創建空:3

空裝:3:請刪除

創建空:4

空裝:4:請刪除我

請刪除我

刪除4:請刪除我

刪除2:刪除

刪除1:我

刪除0:請

這些不會被刪除

請刪除

問題是爲什麼臨時對象在表達式中創建請+ delStrRef +我;不會被刪除。它不應該在表達式的末尾被刪除,或者如果引用是臨時對象而不是對象本身,則會變得不同。

+0

閱讀[此](http://en.wikipedia.org/wiki/Copy_elision)和[此] (http://stackoverflow.com/questions/3106110/what-is-move-semantics),然後停止寫難看的代碼。你沒有保存任何東西。 –

+0

它故意醜陋,因爲我想快速看到實際上用臨時對象做了什麼。這當然不是生產或任何嚴重的事情。 – ognjenmi

+0

但無論如何感謝文章。 – ognjenmi

回答

0
String & String::operator +(String &str) { 
    ... 
    String * strPointer = new String(); 
    ... 
    String &result = *strPointer; 
    ... 
    return result; 
} 

您手動創建了該對象,然後返回對其的引用。因此,編譯器沒有插入delete運算符。所以,你不能返回引用沒有內存泄漏和手動destroing對象。

例如在Qtoperator+作爲

Q_EXPORT inline const QString operator+(const QString &s1, const QString &s2) { 
    QString tmp(s1); 
    tmp += s2; 
    return tmp; 
} 

實現,其中operator+=聲明爲QString &operator+=(const QString &str);