C++ 使用链表的自定义字符串类中的重载 + 运算符

C++ Overloaded + operator in a custom string class using linked list

本文关键字:重载 运算符 自定义 链表 C++ 字符串      更新时间:2023-10-16

在与我的老师进行了相当长时间的会议并且无法提出具体的解决方案之后,我想我会回到这里寻求家庭作业的帮助。我们应该将字符串类转换为我们自己的版本,该版本使用带有一些基本函数的链表。到目前为止,除了 + 运算符函数(将两个字符串加在一起)之外,一切似乎都可以正常工作。

string operator +(string& s1, string& s2);

奇怪的是,它在测试时似乎返回了正确的结果,却导致调试断言失败的崩溃。我不知道为什么会这样,因为定义:

string operator +(string& s1, string& s2)
{
s1 += s2;
return s1;
}

依赖于 +=,但该运算符在 main() 中的测试代码中没有问题。以下是完整代码:

头文件

#ifndef STRING2_H
#define STRING2_H
#include<iostream>
namespace string2
{
class string
{
private:
struct stringList
{
char character;
stringList* link;
};
stringList* headPtr;
public:
// CONSTRUCTORS AND DESTRUCTOR
string() { headPtr = NULL; };
string(const stringList* sourcePtr);
~string();
// CONSTANT MEMBER FUNCTIONS
char getChar(const size_t position) const;
size_t length() const;
char operator [ ] (size_t position) const;
// MODIFICATION MEMBER FUNCTIONS
void operator += (const string& addend);
void operator += (const char addend[]);
void operator += (char addend);
void operator =(const string& source);
// FRIEND FUNCTIONS
friend bool operator ==(const string& s1, const string& s2);
};
// NONMEMBER FUNCTIONS
string operator +(string& s1, string& s2);
std::ostream& operator <<(std::ostream& outs, const string& source);    
}
#endif

实现

#include "String2.h"
#include <iostream>
namespace string2
{
string::string(const stringList* sourcePtr)
{
stringList* indexPtr;
if (sourcePtr == NULL)
{
headPtr = NULL;
return;
}
headPtr = new stringList;
indexPtr = headPtr;
indexPtr->character = sourcePtr->character;
indexPtr->link = sourcePtr->link;
sourcePtr = sourcePtr->link;
while (sourcePtr != NULL)
{
indexPtr = indexPtr->link;
indexPtr->character = sourcePtr->character;
indexPtr->link = sourcePtr->link;
sourcePtr = sourcePtr->link;
}
}
string::~string()
{
stringList *removePtr;;
while (headPtr != NULL)
{
removePtr = headPtr;
headPtr = headPtr->link;
delete removePtr;
}
}
char string::getChar(const size_t position) const
{
stringList *indexPtr = headPtr;
for (size_t i = 0; i < position - 1; i++)
indexPtr = indexPtr->link;
return indexPtr->character;
}
size_t string::length() const
{
size_t count = 0;
stringList* indexPtr = headPtr;
while (indexPtr != NULL)
{
count++;
indexPtr = indexPtr->link;
}
return count;
}
char string::operator [ ] (size_t position) const
{
stringList* indexPtr = headPtr;
for (size_t i = 0; i < position; i++)
indexPtr = indexPtr->link;
return indexPtr->character;
}
void string::operator += (const string& addend)
{
for (int index = 0; index < addend.length(); index++)
(*this) += addend[index];
}
void string::operator += (const char addend[])
{
if (addend[0] == NULL)
return;
for (int index = 0; index < (sizeof(addend) / sizeof(addend[0])); index++)
(*this) += addend[index];
}
void string::operator += (char addend)
{
stringList *indexPtr = headPtr;
if (headPtr == NULL)
{
headPtr = new stringList;
headPtr->character = addend;
headPtr->link = NULL;
return;
}
while (indexPtr->link != NULL)
indexPtr = indexPtr->link;
indexPtr->link = new stringList;
indexPtr->link->character = addend;
indexPtr->link->link = NULL;
}
void string::operator =(const string& source)
{   
if (headPtr != NULL)
{
delete headPtr;
headPtr = NULL;
}
*this += source;
}
bool operator ==(const string& s1, const string& s2)
{
if (s1.length() != s2.length())
return false;
if (s1.headPtr == NULL && s2.headPtr == NULL)
return true;
for (int index = 0; index < s1.length(); index++)
{
if (s1.headPtr->character != s2.headPtr->character)
return false;
}
return true;
}
string operator +(string& s1, string& s2)
{
s1 += s2;
return s1;
}
std::ostream& operator <<(std::ostream& outs, const string& source)
{
for (int index = 0; index < source.length(); index++)
outs << source.getChar(index + 1);
return outs;
}
}

测试代码(最后一行是它中断的地方)

#include "String2.h"
#include <iostream>
#include <fstream>
using namespace string2;
int main()
{
string test, test2, test3;
std::cout << "Current length: " << test.length() << std::endl;
char add[4] = { 'a', 'b', 'c', 'd' };
test += 's'; // testing third (lowest) += operator
std::cout << "First char in string: " << test.getChar(1) << std::endl;
test += 'd';
std::cout << "Current length: " << test.length() << std::endl;
std::cout << "Second char in string:  " << test.getChar(2) << std::endl;
std::cout << "Second char in string testing [] operator: " << test[1] << std::endl;
std::cout << "Current string: " << test << std::endl;
test += add; // testing second (middle) += operator
std::cout << "Current length: " << test.length() << std::endl;
std::cout << "Current string: " << test << std::endl;
test2 += 'z';
test2 += 'y';
test += test2; // testing first (top) += operator
std::cout << "Current string: " << test << std::endl;
test = test2; // testing = operator
std::cout << "nCurrent string: " << test << std::endl;
std::cout << "Compared to string: " << test2 << std::endl;
if (test == test2) // testing == operator
std::cout << "nStrings are equal" << std::endl;
else
std::cout << "nStrings are not equal." << std::endl;
test += 'f';
std::cout << "nCurrent string: " << test << std::endl;
std::cout << "Compared to string: " << test2 << std::endl;
if (test == test2) // testing == operator
std::cout << "nStrings are equal" << std::endl;
else
std::cout << "nStrings are not equal." << std::endl;
std::cout << "nTwo strings added together: " << test + test2 << std::endl; // testing + operator
}

谢谢你的帮助

你的问题是可以重现的

int main()
{
string test, test2;
test += 'h';
std::cout << "nTwo strings added together: " << test + test2 << std::endl; // testing + operator
}
string operator +(string& s1, string& s2)
{
s1 += s2;
return s1;
}

operator +中,return s1返回s1的浅拷贝。所以现在内部存储器被s1以及从operator+()返回的字符串占用。在main()~string()结束时,触发s1释放内部存储器,然后从operator+()返回的字符串,尝试删除已删除的内存,导致双释放。

您需要operator+()或更好的深度副本,重新思考operator+()的设计.