具有核心转储的字符串数组(使用模板和运算符重载)

时间:2015-12-01 04:52:58

标签: c++ arrays string operator-overloading coredump

我试图了解字符串数组和核心转储。因此,我创建了一个类模板,其中包含一些运算符重载函数,用于添加和删除元素。当我在int,double和char专门化上测试加法和减法重载方法时,程序完美地添加和删除了元素(没有核心转储);然而,当在字符串上尝试这个时,我得到一个核心转储。我确保使用#include <string>并使用std :: string。任何人都可以解释为什么这适用于int,double和char特化,但不适用于字符串?

template <class T> T Set<T>::iVal;
template <class T> T Set<T>::DELIM;

template <class T>

//
//default constructor
//
Set<T>::Set ( int s ){

        psize = ( s > 0 ? s: DEFAULTSIZE);
        //allocate an array of specified size
        set = new T[ psize ];

        if(!set) {
                //send an error is system cannot allocate memory
                cout << "Cannot Allocate Memory, exiting program... " << endl;
                exit (1);
        }

        for ( int i = 0; i < psize; i++){
                set[i] = iVal;
        }

        numOfElements = 0;
}

//
//custom constructor
//
template <class T>
Set<T>::Set( T array[] , int size, char name ){

        set = new T[size];

        psize = ( size > 0 ? size: DEFAULTSIZE);
        numOfElements = size;
        for ( int i = 0; i < psize; i++){
                set[i] = array[i];
        }

        if (!set){
                cout << "Cannot Allocate Memory, exiting program... " << endl;
                exit(1);
        }

        Set::name = name;
}

//
//subtraction operator that removes elements
//
template <class T>
bool Set<T>::operator-( T n ){
        bool status = false;
                for ( int i = 0; i < numOfElements; i++){
                        if ( set [i] == n ){
                                for ( int j = i; j < numOfElements; j++){
                                        set [j] = set[j + 1];
                                }

                                set[numOfElements - 1] = n;
                                --numOfElements;
                        }

                        status = true;
                }

                return (status);
}
//
//addition operator that adds elements
//
template <class T>
bool Set<T>::operator+( T n ){
        bool status = false;

        if ( !element(n) ){
                if ( psize == numOfElements ) {
                        T *ptr = new T[psize += 1];

                        for ( int i = 0; i < numOfElements; i++ )
                                ptr[i] = set[i];

                        delete [] set;

                        set = ptr;

                        psize += 1;

                        delete [] ptr;

                }

                set[numOfElements] = n;
                numOfElements += 1;

                status = true;
        }

        return status;

}
//In Driver
 //
        //Creating string arrays using the custom constructor to instantiate objects
        //
        string s1[4] = { "turtle" , "fish", "shark" , "lobster" };
        string s2[3] = { "turtle", "book", "pencil" };

        //
        //Testing string specialization
        //
        cout << "\nTesting strings.\n" << endl;
        Set <string> string1 ( s1, 4, 'A' );
        Set <string> string2 ( s2, 3, 'B' );
        //setting delimiter
        Set <string>::setDELIM ("stop");
        //
        //testing the addition and subtraction of elements
        //CORE DUMP HAPPENS HERE
        string1 - "shark";
        cout << "\nAfter removing an element from Set A, Set A = " << string1 << endl;
        string1 + "dolphin";
        cout << "\nAfter adding an element to Set A, Set A = " << string1 << endl;

1 个答案:

答案 0 :(得分:2)

我看到一些问题都是未定义的行为。它与其他数据类型一起使用的事实可能仅仅是因为运气。

首先,让我们看一下您的-方法:

if ( set [i] == n ){
    for ( int j = i; j < numOfElements; j++){
        set [j] = set[j + 1];  // <-- Access past last element in array
    }

    set[numOfElements - 1] = n;
    --numOfElements;
}

上面的内部循环应该测试j < numOfElements - 1。这样,set[j+1]将不会查看数组末尾之后的元素(如果numOfElements恰好与分配的大小相同)。

现在让我们看看你的+方法:

T *ptr = new T[psize += 1];
for ( int i = 0; i < numOfElements; i++ )
        ptr[i] = set[i];
delete [] set;
set = ptr;
psize += 1;
delete [] ptr;  // <-- BOOM!

在上文中,您刚刚删除了set,然后将其替换为ptr指向的新内存。但后来你删除了那段记忆。如果删除标记的行,这应该可以。