Jim*_*ing 0 c++ delete-operator
我有以下用于实现Bucket课程的文件。但是我无法销毁s 生成的_str析构函数中的成员。我得到的错误是:Bucketoperator+
正常块后检测到堆损坏...CRT 检测到应用程序在堆缓冲区末尾后写入内存
添加两个Bucket对象后总是会出现问题,但是我在调试过程中检查了生成的字符串以及长度是否正确。
另外,如何访问函数_len中的属性operator>>以便分配新值?
头文件:
class Bucket
{
    friend ostream& operator<<(ostream& os, const Bucket& c);
    friend istream& operator>>(istream& is, const Bucket& c);
public:
    Bucket();
    Bucket(const String& str);
    Bucket(const char* str);
    ~Bucket();
    const Bucket operator+(const Bucket& s) const;
    const Bucket operator+(const char* s) const;
    const Bucket& operator=(const char* c);
    const bool operator==(const char* str);
private:
    char* _str;
    int _len;
}; 
源文件:
Bucket::Bucket() {
    _len = 0;
    _str = new char[_len];
}
Bucket::Bucket(const Bucket& myBucket) {
    _len = myBucket._len;
    _str = new char[_len + 1];
    for (int i = 0; i < _len; i++)
        _str[i] = myBucket._str[i];
    _str[_len] = '\0';
}
Bucket::Bucket(const char* str) {
    _len = 0;
    for (int i = 0; str[i] != '\0'; i++) _len++;
    
    _str = new char[_len + 1];
    for (int i = 0; i < _len; i++)
        _str[i] = str[i];
    _str[_len] = '\0';
}
Bucket::~Bucket() {
    if (_len > 0) delete[] _str;
}
const Bucket Bucket::operator+(const Bucket& myBucket) const {
    String tempBucket;
    tempBucket._str = strcat(this->_str, myBucket._str);
    int len = 0;
    
    while (tempBucket._str[len] != '\0') len++;
    tempBucket._str[len] = '\0';
    tempBucket._len = len;
    return tempBucket;
}
const Bucket Bucket::operator+(const char* str) const {
    Bucket tempBucket;
    
    int len = 0;
    tempBucket._len = this->_len;
    for (int i = 0; str[i] != '\0'; i++) tempBucket._len++;
    tempBucket._str = strcat(tempBucket._str, str);
    tempBucket._str[len] = '\0';
    tempBucket._len = len;
    return tempBucket;
}
const Bucket& Bucket::operator=(const char* str) {
    if (this->_str == str) {
        return *this;
    }
    
    _len = 0;
    for (int i = 0; str[i] != '\0'; i++) _len++;
    _str = new char[_len + 1];
    for (int i = 0; i < _len; i++)
        _str[i] = str[i];
    _str[_len] = '\0';
    return *this;
}
const bool Bucket::operator==(const char* str) {
    int comp = strcmp(this->_str, str);
    if (comp == 0) {
        return true;
    }
    else {
        return false;
    }
}
ostream& operator<<(ostream& os, const Bucket& myBucket) {
    os << myBucket._str;
    return os;
}
istream& operator>>(istream& is, const Bucket& myBucket) {
    static char buffer[40];
    is >> buffer;
    int len = 0;
    for (size_t i = 0; buffer[i] != '\0'; i++) {
        myBucket._str[i] = buffer[i];
        len++;
    }
    myBucket._str[len++] = '\0';
    return is;
}
主要的:
int main()
{
    Bucket b1("Hello, "); // This is deleted by the destructor
    Bucket b2(b1); // This is deleted by the destructor
    cout << b1 << b2 << endl; 
    b2 = "Dear ";  // Also works fine
    Bucket b3;
    cout << "Enter a name: ";
    cin >> b3; // Can't assign the _len attribute
    cout << b2 + b3 << ",";  // not destroyed
    Bucket b4(" Please write this sentence after pressing enter:\n");
    b2 = "We believe that ";
    cout << b4 + b2 << b1 << "and " << "Goodbye "  // not destroyed
        << (b1 == "Goodbye " ? "is " : "is not ") << "the same word!\n" <<
        endl;
    return 0;
}
Bucket我发现您的代码的实现方式存在很多问题:
的第二个参数operator>>需要是对非常量对象的引用,否则操作员在从 读取数据时无法修改该对象istream。
根据3/5/0 规则,缺少复制构造函数和复制赋值运算符,并且最好还缺少移动构造函数和移动赋值运算符。
默认构造函数使用 分配内存new[],但由于_len为 0,析构函数不会释放该内存。_len > 0您需要在调用时删除对 的检查delete[]。
默认构造函数不会像其他构造函数那样以空终止分配的数组。
operator+按值返回一个新Bucket对象(应该如此),因此将该对象标记为多余的。const
与返回bool的相同operator==。但是,它operator本身应该标记为const,因为它不会修改Bucket调用它的对象。
两者operator+都使用strcat()不正确。重载Bucket正在修改 的内容this->str_,这是它不应该做的,更糟糕的this->_str是还没有被重新分配以增加其附加内容的能力myBucket._str。过char* 载也犯了类似的错误tempBucket.str_。您需要char[]为每个分配一个全新的数组tempBucket。
Bucket的重载是operator+声明tempBucket为 asString而不是 as Bucket。
operator=通过引用返回修改后的Bucket对象(应该如此),但该对象不应标记为.const
Bucket不公开_str从外部代码访问其成员的方法,因此签if (this->_str == str)入operator==不可能是真实的。
operator=delete[]在用新内存替换旧_str内存之前,不会对旧内存进行处理char[]。
operator>>不会对其buffer读入的内容执行任何边界检查。并且不会重新分配myBucket._str以适应 的内容buffer。并且,它正在计算 中的空终止符_len,而其他类方法都不会这样做。
话虽如此,尝试更像这样的事情:
class Bucket
{
    friend ostream& operator<<(ostream& os, const Bucket& rhs);
    friend istream& operator>>(istream& is, Bucket& rhs);
public:
    Bucket(size_t len = 0);
    Bucket(const Bucket& src);
    Bucket(Bucket&& src);
    Bucket(const char* str);
    Bucket(const char* str, size_t len);
    ~Bucket();
    Bucket operator+(const Bucket& rhs) const;
    Bucket operator+(const char* str) const;
    /*
    Bucket& operator=(const Bucket& rhs);
    Bucket& operator=(Bucket&& rhs);
    Bucket& operator=(const char* str);
    */
    Bucket& operator=(Bucket rhs);
    bool operator==(const Bucket& rhs) const;
    bool operator==(const char* rhs) const;
private:
    char* _str;
    size_t _len;
    void swap(Bucket &other);
    bool equals(const char* str, size_t len) const;
    Bucket concat(const char* str, size_t len) const;
};
static size_t my_strlen(const char* str) {
    const char* start = str;
    if (str) while (*str != '\0') ++str;
    return (str - start);
}
Bucket::Bucket(size_t len) {
    _len = len;
    if (len > 0) {
        _str = new char[len + 1];
        _str[len] = '\0';
    }
    else {
        _str = nullptr;
    }
}
Bucket::Bucket(const Bucket& src)
    : Bucket(src._str, src._len) { }
Bucket::Bucket(Bucket&& src) : Bucket(0) {
    src.swap(*this);
}
Bucket::Bucket(const char* str)
    : Bucket(str, my_strlen(str)) { }
    
Bucket::Bucket(const char* str, size_t len) : Bucket(len) {
    if (str && len > 0) {
        for(size_t i = 0; i < len; ++i) {
            _str[i] = str[i];
        }
    }
}
Bucket::~Bucket() {
    delete[] _str;
}
void Bucket::swap(Bucket &other) {
    char *ptmp = _str;
    _str = other._str;
    other._str = ptmp;
    size_t itmp = _len;
    _len = other._len;
    other._len = itmp;
}
bool Bucket::equals(const char* str, size_t len) const {
    if (this->_len != len) return false;
    for(size_t i = 0; i < len; ++i) {
        if (this->_str[i] != str[i]) return false;
    }
    return true;
}
Bucket Bucket::concat(const char* str, size_t len) const {
    Bucket tempBucket(this->_len + len);
    for(size_t i = 0; i < this->_len; ++i) {
        tempBucket._str[i] = this->_str[i];
    }
    for(size_t i = this->_len, j = 0; j < len; ++i, ++j) {
        tempBucket._str[i] = str[j];
    }
    return tempBucket;
}
Bucket Bucket::operator+(const Bucket& rhs) const {
    return concat(rhs._str, rhs._len);
}
Bucket Bucket::operator+(const char* rhs) const {
    return concat(rhs, my_strlen(rhs));
}
/*
Bucket& Bucket::operator=(const Bucket& rhs) {
    if (this != &rhs) {
        Bucket(rhs).swap(*this);
    }
    return *this;
}
Bucket& Bucket::operator=(Bucket&& rhs) {
    Bucket(std::move(rhs)).swap(*this);
    return *this;
}
Bucket& Bucket::operator=(const char* rhs) {
    Bucket(rhs).swap(*this);
    return *this;
}
*/
Bucket& Bucket::operator=(Bucket rhs) {
    rhs.swap(*this);
    return *this;
}
bool Bucket::operator==(const Bucket& rhs) const {
    return equals(rhs._str, rhs._len);
}
bool Bucket::operator==(const char* rhs) const {
    return equals(rhs._str, my_strlen(rhs));
}
ostream& operator<<(ostream& os, const Bucket& rhs) {
    os.write(rhs._str, rhs._len);
    return os;
}
istream& operator>>(istream& is, Bucket& rhs) {
    /*
    string buffer;
    is >> buffer;
    rhs = buffer.c_str();
    return is;
    */
    char buffer[40];
    if (!is.get(buffer, 40)) buffer[0] = '\0';
    rhs = buffer;
    return is;
}
话虽这么说,如果您可以使用标准 C++ 功能,例如  std::string,那么代码就会变得简单得多:
#include <string>
class Bucket
{
    friend ostream& operator<<(ostream& os, const Bucket& rhs);
    friend istream& operator>>(istream& is, Bucket& rhs);
public:
    Bucket() = default;
    Bucket(const Bucket& src) = default;
    Bucket(Bucket&& src) = default;
    ~Bucket() = default;
    Bucket(const std::string& str);
    Bucket operator+(const Bucket& rhs) const;
    Bucket& operator=(const Bucket& rhs) = default;
    Bucket& operator=(Bucket&& rhs) = default;
    bool operator==(const Bucket& rhs) const;
private:
    std::string _str;
};
Bucket::Bucket(const std::string str) : _str(str) { }
Bucket Bucket::operator+(const Bucket& rhs) const {
    return Bucket(this->_str + rhs._str);
}
bool Bucket::operator==(const Bucket& rhs) const {
    return (this->_str == rhs._str);
}
ostream& operator<<(ostream& os, const Bucket& rhs) {
    os.write << rhs._str;
    return os;
}
istream& operator>>(istream& is, Bucket& rhs) {
    is >> rhs._str;
    return is;
}