2011-10-05 97 views
3

我對C++相當陌生,對指針也很陌生。我目前正在研究一個堆棧,並試圖重新分配堆棧的內存,因爲堆棧的大小達到頂端,但是我遇到了問題。我已經在Google和堆棧溢出方面做了很多研究,並且發現了一些有用的信息,但是因爲我對堆棧和C++都很陌生,所以我仍然遇到問題。我希望一些明亮而聰明的人至少能指引我朝着正確的方向前進。動態堆棧內存重新分配

現在...這是我的代碼。

#include <iostream> 
#define STACKMAX 20 
using namespace std; 

template <class T> class StackTemplated { 
private: 
    int top; 
    T values[STACKMAX]; 
public: 
    StackTemplated(); 
    void push(T i); 
    T  pop(void); 
    bool empty(void); 
}; 


template <class T> StackTemplated<T>::StackTemplated() { 
    top = -1; 
} 

template <class T>void StackTemplated<T>::push(T i) { 
if (top == STACKMAX - 1) { 

    // reallocate top of stack. (this is the area I'm having issues) 
    char * string1; 
    string1 = (char *)calloc(STACKMAX, sizeof(char)); 

     if (top == STACKMAX - 1) { 
      cout << "The stack didn't re-allocate."; 
      exit(1); 
     } 

} else { 
    top++; 
    values[top] = i; 
} 
} 

template <class T> T StackTemplated<T>::pop(void) { 
if (top < 0) { 
    printf("%", "Stack underflow!"); 
    exit(1); 
} else { 
    return values[top--]; 
} 
} 

template <class T> bool StackTemplated<T>::empty() { 
return (top == -1); 
} 
+1

請注意,「C/C++」不是一種語言。 C和C++是獨立的語言;在這種情況下,您正在使用C++。 – Cameron

+0

我已經刪除了問題和標籤中對C的引用。 –

+0

讓'pop()'返回一個對象以及彈出一個對象是一個相當不好的設計。這使得以異常安全的方式使用堆棧非常困難(這使得強壯的異常安全保證特別難以實現),因爲從堆棧中彈出該值(其修改堆棧)的操作之後是操作將返回值複製到調用者的代碼中(可能會拋出)。 (有關此事的更多討論,請參見[這裏](http://www.gotw.ca/gotw/008.htm)。) – Mankarse

回答

1

問題是你不想重新分配堆棧的頂部。相反,你想分配一個足夠大的新數組來保存新值。另外,由於您需要重新分配陣列,values應該是一個指針。

但是我們如何忘記這一切。如果我們使用C++,讓我們使用C++提供給我們的東西,讓我們的生活更輕鬆。在完成之後,如果你真的覺得需要,可以試着打開它。

我指的是你使用calloc。使用calloc是一個不好的想法,特別是在使用模板時。問題是因爲calloc沒有類型信息,所以它不會像調用構造函數那樣做一些基本的事情。構造函數是在OOP中非常重要的,因爲它們保證了對象在創建時的不變性。而是,使用new[]關鍵字,像

values = new T[STACKMAX]; 

該分配的STACKMAX長度的T陣列。當然,正如Greg指出的那樣,您應該重新考慮使用STACKMAX,並改用變量。另外,values不應該是一個靜態數組,而應該改爲T*

我指的另一件事是,你真的想要實現一個根據需要動態增長的數組。在C++中,我們稱這種結構爲vector。如果您使用矢量,您的整個代碼縮小到

#include<iostream> 
#include<vector> 

using namespace std; 

template<class T> class StackTemplated { 
private: 
    std::vector<T> vec; 

public: 
    StackTemplated() { } // the constructor is trivial; in fact, you can leave it out if you want 
    void push(T i); 
    T  pop(void); 
    bool empty(void); 
}; 

template<class T> 
void StackTemplated<T>::push(T i) { 
    vec.push_back(i); 
} 

template<class T> 
T StackTemplate<T>::pop(void) { 
    T top = vec.back(); 
    vec.pop_back(); 
    return top; 
} 

template<class T> 
bool StackTemplate<T>::isEmpty(void) { 
    return vec.size() == 0; 
} 

就是這樣。如果你可以使用現有的數據結構來實現新的數據結構,那麼它就少了很多。

一旦你對vector的工作方式(以及網絡上的大量解釋/文檔)非常滿意,然後嘗試自己實現功能。底線是,如果你確切地知道它應該如何表現,實現一個數據結構要容易得多。

3

這裏有幾件事情,我注意到一個列表:

  • STACKMAX是一個常數。如果你正在擴展堆棧,你將如何跟蹤它目前有多大?
  • values成員是一個固定大小的數組。您將無法動態更改其大小,而無需更改其聲明和分配方式。
  • calloc()以您指定的字節數分配新的內存塊。你需要以某種方式將現有的堆棧複製到新的內存塊中,並釋放前一個堆棧。
  • 您在撥打calloc()時只分配STACKMAX字節。如果T不是char,您可能希望按比例縮小sizeof T

一旦你解決了這些重要問題,會有很多細節供你修復。祝你好運。

0

我將宣佈自己的價值觀像

T* vaules; 

然後使用新創建它不釋放calloc。您需要跟蹤堆棧的頂部和大小。正如格雷格在堆棧中說的那樣,確保將數據複製並清理舊數據。