带核心转储的字符串数组(使用模板和运算符重载)
String array with Core Dump (using templates and operator overloading)
我想了解一些关于字符串数组和核心转储的内容。因此,我创建了一个 class 模板,其中包含一些用于添加和删除元素的运算符重载函数。当我在 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;
我看到一些问题都是未定义的行为。它适用于其他数据类型的事实可能只是运气。
首先,让我们看看您的 -
方法:
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
指向的新内存替换了它。但后来你删除了那段记忆。如果您删除标记的行,这应该有效。
我想了解一些关于字符串数组和核心转储的内容。因此,我创建了一个 class 模板,其中包含一些用于添加和删除元素的运算符重载函数。当我在 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;
我看到一些问题都是未定义的行为。它适用于其他数据类型的事实可能只是运气。
首先,让我们看看您的 -
方法:
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
指向的新内存替换了它。但后来你删除了那段记忆。如果您删除标记的行,这应该有效。