因此我正在使用智能指针创建自己的字符串类(因此我可以习惯它们),除了运算符+()函数之外,它一直很顺利。
它不断崩溃程序,当VS调试程序时,析构函数抛出异常。我似乎无法确定原因,这是导致程序崩溃的唯一函数,即使我删除所有算法,只返回一个mystring
对象。
有什么建议吗?
#include <iostream>
#include <string>
#include <memory>
#include <cstring>
using namespace std;
class mystring {
public:
mystring() : word(make_unique<char[]>('\0')), len(0) {}
~mystring() { cout << "goodbye objects!";}
mystring(const char *message) : word(make_unique<char[]>(strlen(message) + 1)), len(strlen(message)) {
for (int i = 0; i < len; i++) word[i] = message[i];
word[len] = '\0';
}
mystring(const mystring &rhs) : word(make_unique<char[]>(rhs.len)), len(rhs.len + 1) {
for (int i = 0; i < len; i++) word[i] = rhs.word[i];
word[len] = '\0';
}
mystring &operator=(const mystring &rhs) {
if (this != &rhs) {
releaseWord();
word = make_unique<char[]>(rhs.len + 1);
len = rhs.len;
for (int i = 0; i < len; i++) word[i] = rhs.word[i];
word[len] = '\0';
}
return *this;
}
//what is wrong with this function/what should be changed?
friend mystring operator+(const mystring& lhs, const mystring& rhs) {
mystring Result;
int lhsLength = lhs.len, rhsLength = rhs.len;
Result.releaseWord();
Result.word = make_unique<char[]>(lhsLength + rhsLength + 1);
Result.len = lhsLength + rhsLength;
for (int i = 0; i < lhsLength; i++) Result.word[i] = lhs.word[i];
for (int j = lhsLength; j < Result.len; j++) Result.word[j] = rhs.word[j];
Result.word[Result.len] = '\0';
return Result;
}
friend ostream &operator<<(ostream &os, const mystring &message) {
return os << message.word.get();
}
int size() const {
return len;
}
private:
int len;
unique_ptr<char[]> word;
void releaseWord() {
char *temp = word.release();
delete[] temp;
}
};
int main()
{
mystring word1 = "Darien", word2 = "Miller", word3;
cout << word1 + word2;//causes heap corruption
word3 = word1 + word2; //causes heap corruption
return 0;
}
答案 0 :(得分:1)
这一行的问题:
for (int j = lhsLength; j < Result.len; j++) Result.word[j] = rhs.word[j];
j rhs.word[j];
应该是rhs.word[j-lhsLength];
你正在破坏数组限制
答案 1 :(得分:0)
您的operator+
未正确复制rhs
中的字符,因为它使用了错误的索引来遍历rhs.word[]
。它看起来应该是这样的:
friend mystring operator+(const mystring& lhs, const mystring& rhs) {
mystring Result;
int lhsLength = lhs.len, rhsLength = rhs.len;
Result.word = make_unique<char[]>(lhsLength + rhsLength + 1);
Result.len = lhsLength + rhsLength;
for (int i = 0; i < lhsLength; i++)
Result.word[i] = lhs.word[i];
for (int i = lhsLength, j = 0; i < Result.len; i++, j++)
Result.word[i] = rhs.word[j];
Result.word[Result.len] = '\0';
return Result;
}
另一种选择是使用std::copy_n()
而不是手动循环:
#include <algorithm>
friend mystring operator+(const mystring& lhs, const mystring& rhs) {
mystring Result;
Result.word = make_unique<char[]>(lhs.len + rhs.len + 1);
Result.len = lhs.len + rhs.len;
std::copy_n(lhs.word.get(), lhs.len, Result.word.get());
std::copy_n(rhs.word.get(), rhs.len, Result.word.get() + lhs.len);
Result.word[Result.len] = '\0';
return Result;
}
此外,您的默认和复制构造函数未正确设置成员(例如,您的复制构造函数没有为空终止符分配足够的空间,并且正在设置len
以包含空终止符)。
并且,您的ReleaseWord
方法是不必要的,您也应该考虑实现移动语义。
尝试更像这样的事情:
#include <iostream>
#include <string>
#include <memory>
#include <cstring>
#include <algorithm>
using namespace std;
class mystring {
public:
mystring() : len(0), word(make_unique<char[]>(1)) {
word[0] = '\0';
}
~mystring() {
cout << "goodbye objects!";
}
mystring(const char *message) : len(strlen(message)), word(make_unique<char[]>(len + 1)) {
copy_n(message, len, word.get());
word[len] = '\0';
}
mystring(const mystring &rhs) : len(rhs.len), word(make_unique<char[]>(len + 1)) {
copy_n(rhs.word.get(), rhs.len, word.get());
word[len] = '\0';
}
mystring(mystring &&rhs) : len(rhs.len), word(std::move(rhs.word)) {
}
mystring& operator=(const mystring &rhs) {
if (this != &rhs) {
mystring tmp(rhs);
swap(word, tmp.word);
swap(len, tmp.len);
}
return *this;
}
mystring& operator=(mystring &&rhs) {
swap(word, rhs.word);
swap(len, rhs.len);
return *this;
}
friend mystring operator+(const mystring& lhs, const mystring& rhs) {
mystring Result;
Result.len = lhs.len + rhs.len;
Result.word = make_unique<char[]>(Result.len + 1);
std::copy_n(lhs.word.get(), lhs.len, Result.word.get());
std::copy_n(rhs.word.get(), rhs.len, Result.word.get() + lhs.len);
Result.word[Result.len] = '\0';
return Result;
}
friend ostream &operator<<(ostream &os, const mystring &message) {
return os << message.word.get();
}
int size() const {
return len;
}
private:
int len;
unique_ptr<char[]> word;
};