C++ 自定义字符串类中的堆损坏

C++ 自定义字符串类中的堆损坏,c++,string,C++,String,因此,当我使用智能指针创建我自己的字符串类时(这样我就可以习惯它们),除了操作符+()函数外,它基本上进展顺利 它不断使程序崩溃,当VS调试程序时,析构函数抛出异常。我似乎无法找出原因,这是导致程序崩溃的唯一函数,即使我删除了所有算法,只返回一个mystring对象 有什么建议吗 #include <iostream> #include <string> #include <memory> #include <cstring> using nam

因此,当我使用智能指针创建我自己的字符串类时(这样我就可以习惯它们),除了操作符+()函数外,它基本上进展顺利

它不断使程序崩溃,当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;
}
#包括
#包括
#包括
#包括
使用名称空间std;
类mystring{
公众:
mystring():word(使_唯一('\0')),len(0){
~mystring(){cout这行中的问题:

for (int j = lhsLength; j < Result.len; j++) Result.word[j] = rhs.word[j];
for(int j=lhsLength;j
对于
rhs.word[j];

应该类似于
rhs.word[j-lhsLength];


您正在突破数组限制

您的
操作符+
没有正确地从
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;
} 
此外,默认构造函数和复制构造函数没有正确设置成员(例如,复制构造函数没有为空终止符分配足够的空间,并且正在将
len
设置为包含空终止符)

和,您的<代码> RelaseWord < /Cult>方法是不必要的,并且您也应该考虑实现移动语义。

尝试类似以下内容:

#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;
};
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
类mystring{
公众:
mystring():len(0),word(使_唯一(1)){
字[0]='\0';
}
~mystring(){

在某些地方(如复制构造函数和默认构造函数),您忘记为空终止符留出空间。请注意,
make_unique('\0')
分配零字节,因为
'\0'
只是编写0的另一种方式。啊,好吧,这很有意义。如果我改为这样做,会是这样吗?mystring():len(0),word(make_unique(1)){word[0]='\0';}如果运算符=返回常量mystring&,则效果更好,但这似乎不是您的问题。这非常有帮助,谢谢!!另外,通过查看您的解决方案,我注意到了一些对我来说是新的部分,特别是这段代码:
mystring(mystring&&rhs):len(rhs.len),word(std::move(rhs.word)){}
这个函数的目的是什么,以及双“&”?谢谢!@DarienMiller它是一个移动构造函数,它转移现有分配内存的所有权,而不是分配新内存。请阅读“右值引用”和“移动语义”,这是在C++11中添加的(显然您使用的是C++14或更高版本,因为您使用的是在C++14中添加的
std::make_unique()
)。
#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;
};