2015-09-23 50 views
0

請在回答問題前參閱下面的程序。在評論中解釋代碼。分配操作員超載:錯誤處理方案

所以我的問題是在賦值運算符重載如何處理new()未能分配內存的情況。

例如Obj1持有字符串"GeeksQuiz"。指定Obj2Obj1。在分配期間(在分配操作員過載功能中),首先我們釋放Obj1,然後用Obj2值重新創建Obj1。那麼在new未能分配內存的情況下如何保留舊的Obj1值?由於我們在函數啓動時釋放了Obj1值。

我想要的是當分配操作失敗時,舊的值爲Obj1

請幫我這個。我想完美的代碼,沒有任何內存泄漏覆蓋所有場景。提前致謝

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

class String 
{ 
private: 
    char *string_data; 
    int size; 
public: 
    String(const char *str = NULL); // constructor 
    ~String() { delete [] string_data; }// destructor 
    void print() { cout << string_data << endl; } // Function to print string 
    String& operator = (const String &); // assignment operator overload 
}; 

String::String(const char *str) // Constructor 
{ 
    size = strlen(str); 
    string_data = new char[size+1]; 
    if (string_data != NULL) 
     strcpy(string_data, str); 
    else 
     cout<<"compiler failed to allocate new memory"; 
} 

String& String::operator = (const String &str) // assignment operator overload 
{ 
    if(this != &str) 
    { 
     delete [] string_data; // Deleting old data and assigning new data below 
     size = str.size; 
     string_data = new char[size+1]; 
     if(string_data != NULL) // This condition is for cheking new memory is success 
      strcpy(string_data, str.string_data); 
     else 
      cout<<"compiler failed to allocate new memory"; // My quetsion comes in this scenario... 
    } 
    return *this; 
} 

int main() 
{ 
    String Obj1("GeeksQuiz"); 
    String Obj2("stackoverflow"); 

    Obj1.print(); // Printing Before assigment 
    Obj2.print(); 

    Obj1 = Obj2; // Assignment is done. 

    Obj1.print(); // Printing After assigment 
    Obj2.print(); 
    return 0; 
} 
+1

先分配,然後如果全部刪除舊數據。 –

+0

您賦值運算符中的「if」路徑不返回任何內容。 – Drax

+0

爲什麼你認爲你可以 - 爲了好玩(或練習?) - 實現一個健壯的字符串類?如果你想用C++編程,學習使用它的標準庫! – Wolf

回答

2

首先,實現一個健壯的字符串是困難的,除非你想爲了學習的目的而使用它,總是使用std::string

然後考慮到operator new總是返回非空指針(除非你也執行非標定製new運營商),而是拋出一個異常std::bad_alloc如果無法分配數據。如果你要處理的分配失敗的情況下,你需要添加一個try-catch塊

char *data = NULL; 
try { 
    data = new char[str.size + 1]; 
} catch (std::bad_alloc &e) { 
    std::cout << "Allocation failed: " << e.what() << std::endl; 
    throw; // <- You probably want to rethrow the exception. 
} 
strcpy(data, str.string_data); 
delete [] string_data; 
string_data = data; 
size = str.size; 

最重要的部分是要離開你的類時拋出異常一致的狀態,這就是爲什麼你必須先分配新數據,然後如果成功,則刪除舊數據。然而,bad_alloc異常很少在類級別處理,通常你會拋出異常(這就是爲什麼我重新拋出代碼示例)並讓客戶端代碼處理它。

如果你真的想讓你的代碼成爲例外證明,我會建議使用智能指針,並且如前所述,在這種情況下使用std::string

+0

我會強調首先使用'std :: string'的重要性,而不是(如果有的話)談論處理'std :: bad_alloc' – Wolf

+0

@Wolf,同意。改變了。 – nsubiron

2

臨時或虛擬變量。

分配新內存,將指針分配給臨時變量。如果它成功然後釋放舊的內存並重新分配該指針變量。


僞上下的代碼:在臨時變量

char *temp = new char[new_size]; 
std::copy(new_data, new_data + new_size, temp); 
delete [] old_data; 
old_data = temp; 
old_size = new_size; 
+0

您能否爲該功能添加正確的代碼 – Bubbles

+0

您的*僞代碼*看起來非常不正確。故意地? – Wolf

+0

@Wolf你爲什麼這麼說?如果這些變量被定義,那實際上是四個完全有效的陳述。 –

0

1日分配內存,如果成功則僅刪除舊的價值。

+0

String&String :: operator =(const String&str)//賦值運算符過載 { if(this !=&str)//自我分配檢查 { int temp_int = str.size; char * temp_string = new char [size + 1]; strcpy(temp_string,str.string_data); if(string_data!= NULL)//這個條件用於檢測新內存是否成功 size = temp_int; delete [] string_data; strcpy(string_data,temp_string); } else cout <<「編譯器未能分配新內存」; } return * this; } – Bubbles

+0

我在指針字符串複製東西弱。 Cna請檢查並覈對我 – Bubbles

+0

String&String :: operator =(const String&str)//賦值運算符過載 { if(this!=&str) { size = str.size; char * string_data_temp = new char [size + 1]; 如果(string_data_temp!= NULL)//該條件爲cheking新存儲器是成功 \t \t { \t \t \t刪除[] string_data; //現在刪除 \t \t \t string_data = string_data_temp; strcpy(string_data,str.string_data); \t \t} else cout <<「編譯器未能分配新內存」; //我的quetsion出現在這種情況下... } return * this; } –