2017-03-14 10 views
0

私は、SimpleVectorのpush_backとpop_back関数を作成します。私はこの方法で既存の配列に要素を追加しようとしていますが、機能しません。それは私がメインで渡す番号の代わりに0を追加します。理由は何ですか?配列の "push_back"ファンクションの作成

SimpleVector.h

// SimpleVector class template 
#ifndef SIMPLEVECTOR_H 
#define SIMPLEVECTOR_H 
#include <iostream> 
#include <new>  // Needed for bad_alloc exception 
#include <cstdlib> // Needed for the exit function 

using namespace std; 

template<class T> 
class SimpleVector 
{ 
private: 
    T *aptr;   // To point to the allocated array 
    int arraySize; // Number of elements in the array 
    void memError(); // Handles memory allocation errors 
    void subError(); // Handles subscripts out of range 

public: 
    // Default constructor 
    SimpleVector() 
    { 
     aptr = 0; 
     arraySize = 0; 
    } 

    // Constructor declaration 
    SimpleVector(int); 

    // Copy constructor declaration 
    SimpleVector(const SimpleVector &); 

    // Destructor declaration 
    ~SimpleVector(); 

    // Accessor to return the array size 
    int size() const 
    { 
     return arraySize; 
    } 

    // Accessor to return a specific element 
    T getElementAt(int position); 

    // Overloaded [] operator declaration 
    T &operator[](const int &); 

    void push_back(SimpleVector, int); 

    void pop_back(SimpleVector, int); 
}; 

//*********************************************************** 
// Constructor for SimpleVector class. Sets the size of the * 
// array and allocates memory for it.      * 
//*********************************************************** 

template<class T> 
SimpleVector<T>::SimpleVector(int s) 
{ 
    arraySize = s; 
    // Allocate memory for the array. 
    try 
    { 
     aptr = new T[s]; 
    } 
    catch (bad_alloc) 
    { 
     memError(); 
    } 

    // Initialize the array. 
    for (int count = 0; count < arraySize; count++) 
     *(aptr + count) = 0; 
} 

//******************************************* 
// Copy Constructor for SimpleVector class. * 
//******************************************* 

template<class T> 
SimpleVector<T>::SimpleVector(const SimpleVector &obj) 
{ 
    // Copy the array size. 
    arraySize = obj.arraySize; 

    // Allocate memory for the array. 
    aptr = new T[arraySize]; 
    if (aptr == 0) 
     memError(); 

    // Copy the elements of obj's array. 
    for (int count = 0; count < arraySize; count++) 
     *(aptr + count) = *(obj.aptr + count); 
} 

//************************************** 
// Destructor for SimpleVector class. * 
//************************************** 

template<class T> 
SimpleVector<T>::~SimpleVector() 
{ 
    if (arraySize > 0) 
     delete[] aptr; 
} 

//******************************************************* 
// memError function. Displays an error message and  * 
// terminates the program when memory allocation fails. * 
//******************************************************* 

template<class T> 
void SimpleVector<T>::memError() 
{ 
    cout << "ERROR:Cannot allocate memory.\n"; 
    exit(EXIT_FAILURE); 
} 

//*********************************************************** 
// subError function. Displays an error message and   * 
// terminates the program when a subscript is out of range. * 
//*********************************************************** 

template<class T> 
void SimpleVector<T>::subError() 
{ 
    cout << "ERROR: Subscript out of range.\n"; 
    exit(EXIT_FAILURE); 
} 

//******************************************************* 
// getElementAt function. The argument is a subscript. * 
// This function returns the value stored at the sub- * 
// script in the array.         * 
//******************************************************* 

template<class T> 
T SimpleVector<T>::getElementAt(int sub) 
{ 
    if (sub < 0 || sub >= arraySize) 
     subError(); 
    return aptr[sub]; 
} 

//******************************************************* 
// Overloaded [] operator. The argument is a subscript. * 
// This function returns a reference to the element  * 
// in the array indexed by the subscript.    * 
//******************************************************* 

template<class T> 
T &SimpleVector<T>::operator[](const int &sub) 
{ 
    if (sub < 0 || sub >= arraySize) 
     subError(); 
    return aptr[sub]; 
} 
#endif 

template<class T> 
void SimpleVector<T>::push_back(SimpleVector obj, int newval) 
{ 
    arraySize = obj.arraySize + 1; 

    // Allocate memory for the array. 
    aptr = new T[arraySize]; 
    if (aptr == 0) 
     memError(); 

    // Copy the elements of obj's array. 
    for (int count = 0; count < (arraySize - 1); count++) 
     *(aptr + count) = *(obj.aptr + count); 

    obj.aptr[(arraySize)] = newval; 

} 

main.cppに

// This program demonstrates the SimpleVector template. 
#include <iostream> 
#include "SimpleVector.h" 
using namespace std; 

int main() 
{ 
    const int SIZE = 10; // Number of elements 
    int amtToPrnt = 10; 
    int count; // Loop counter 

// Create a SimpleVector of ints. 
    SimpleVector<int> intTable(SIZE); 

// Store values in the two SimpleVectors. 
    for (count = 0; count < SIZE; count++) 
    { 
     intTable[count] = (count * 2); 
    } 

// Display the values in the SimpleVectors. 
    cout << "These values are in intTable:\n"; 
    for (count = 0; count < amtToPrnt; count++) 
     cout << intTable[count] << " "; 
    cout << endl; 

    intTable.push_back(intTable, 20); 
    cout << "These values are in intTable after adding one more value:\n"; 
    for (count = 0; count < ++amtToPrnt; count++) 
     cout << intTable[count] << " "; 
    cout << endl; 

    /* 
    intTable.push_back(intTable, 22); 
    cout << "These values are in intTable after adding one more value:\n"; 
    for (count = 0; count < ++amtToPrnt; count++) 
    cout << intTable[count] << " "; 
    cout << endl; 

    intTable.push_back(intTable, 24); 
    cout << "These values are in intTable after adding one more value:\n"; 
    for (count = 0; count < ++amtToPrnt; count++) 
    cout << intTable[count] << " "; 
    cout << endl; 
    */ 
    return 0; 
} 
+0

オフトピック:ヘッダーのインクルードガードが早すぎると閉じます。 – user4581301

答えて

1

SimpleVector。時間

void push_back(int); 

私はメモリ使用量を減らすためにSimpleVectorを削除します。

template <class T> 
void SimpleVector<T>::push_back(int newval){ 
    // Allocate memory for the array in the temporary array. 
    T * tmpArray = new T [arraySize + 1]; 

    // Copy the elements of old array. 
    for(int count = 0; count < arraySize; count++) 
     *(tmpArray + count) = *(aptr + count); 

    // Push new value 
    *(tmpArray + arraySize) = newval; 

    // Delete old array 
    delete[] aptr; 

    // Copy array 
    aptr = tmpArray; 

    // Increase size 
    arraySize++; 
} 

main.cppに

intTable.push_back(20); 
amtToPrnt++; 

cout << "These values are in intTable after adding one more value:\n"; 
for (count = 0; count < amtToPrnt; count++) 
    cout << intTable[count] << " "; 
cout << endl; 

結果:

enter image description here

サイドノート: あなたSimpleVectorをリファクタリングする必要があります。あなたがそれを必要としなかった場合、価値渡しを使用しないでください。そして、あなたのvectorにいくつのデータがあるのか​​を公開するように、arraySizeを公開することをお勧めします。

+0

ありがとうございます! – EggplantMachina

1

SimpleVector<T>::push_backは、ちょっと難解です。見てみようか?

void SimpleVector<T>::push_back(SimpleVector obj, int newval) 

SimpleVector obj値によって渡され、そうで動作objがコピーされます。参照渡しをお勧めします。しかし、なぜこれを最初にやっていますか? SimpleVectorと新しい値をプッシュバックするpush_backは何ですか?このアプローチを再考することを推奨します。

{ 
    arraySize = obj.arraySize + 1; 

    // Allocate memory for the array. 
    aptr = new T[arraySize]; 

でもOKです。それはすべて良いです。ただし、aptrがすでにメモリを指している場合はどうなりますか?最初にdelete[]にする必要がありますが、何をコピーしますか?ここで一時変数を使用し、コピーと削除が完了した後に一時変数を割り当てることをお勧めします。

if (aptr == 0) 
     memError(); 

これは決して起こりません。 newは割り当てエラーでbad_allocをスローするので、newが失敗した場合、プログラムはここに到着しません。先にプログラムはこれを行いました:

try 
{ 
    aptr = new T[s]; 
} 
catch (bad_alloc) 
{ 
    memError(); 
} 

あなたはもう一度やり直したいと思うでしょう。

nullptrの代わりに0を使用することも悪い形式です。0はマジックナンバーであり、ポインタではありません。

// Copy the elements of obj's array. 
    for (int count = 0; count < (arraySize - 1); count++) 
     *(aptr + count) = *(obj.aptr + count); 

すべてgroovyです。 aptr[count]が充分満足していると思われる、頑丈なポインタの算術演算以外には、ここで見ることはありません。しかし、上記で概説したように、これはpush_back関数の予期しない動作です。

obj.aptr[(arraySize)] = newval; 

objはまだobj.arraySizeなサイズであるとarraySizeは大きなものです。次に、配列は0 .. obj.arraySize-1というインデックスが付けられます。したがって、配列の末尾を過ぎて1つではなく2つの要素が書き込まれ、未定義のビヘイビアが呼び出されます。これを行うことによって何が起こるかは誰が知っていますか?私は確かにしません。

次に、破棄しようとしているコピーであるobjを変更します。私は*(aptr + arraySize - 1) = newval;がより有用だろうと思う。

} 

私はこれを書いていましたが、これは完璧に役立つ何を答えが上がったのですか?それを参照してください。

最適化:常に1ずつ増加するのではなく、サイズ変更とコピーをたくさん節約し、サイズを2倍に増やしてみましょう。

0

push_backを呼び出すと、最初のパラメータが値渡しされます。つまり、一時的なコピーが作成されます。次に、新しい配列を割り当てます(元のメモリリークを削除せずに)!thisのptrを新しい配列に変更します。ファインですが、新しい値を一時的なベクトルに入れます。一時的なベクトルは、関数から戻った後に破棄されます。

関連する問題