【问题标题】:Istream operator overloading '>>' cause infinite loopIstream 运算符重载 '>>' 导致无限循环
【发布时间】:2018-11-08 21:09:42
【问题描述】:

我的大学老师布置了一个关于模拟字符串的作业,这是我的一段代码:

// MyString.h
#include <iostream>
#include <cstdio>
#include <string.h>

using std::ostream;
using std::istream;

class MyString{
protected:
    char *_data;                // data index
    int  _len;                  // index size
public:
/////////////////////////////////////////////////////////
    char* data()const{
        return _data;
    }
/////////////////////////////////////////////////////////

    MyString& operator=(const char* &rhs){
        _data = const_cast<char*>(rhs);
        _len  = strlen(_data)
    }

    MyString& operator=(const MyString& rhs){
        (*this) = rhs._data;
    }
/////////////////////////////////////////////////////////
    friend ostream &operator<<( ostream&, const MyString & );
    friend istream &operator>>( istream&, MyString & );
};


ostream& operator <<(ostream& os, const MyString& str){
    os << str.data();
    return os;
}

istream& operator >>(istream& is, MyString& str){
    char buffer[0xff];
    is.getline(buffer, 0xff);
    str = buffer;
    return is;
}

我完全不知道为什么operator = 会在这里导致无限循环...请帮助...提前致谢

编辑: 这是我的错误代码。我已经编辑了导致无限循环问题的原因,但其余的可能仍然存在错误,我会尽快修复它们,谢谢大家!

MyString.h

#include <iostream>
#include <cstdio>
#include <string.h>

using std::ostream;
using std::istream;

class MyString{
protected:
    char *_data;                // data index
    int  _len;                  // index length
    static int _total_MyString; // number of instance created
public:
/////////////////////////////////////////////////////////
    // basic initialization
    MyString(){
        _data = NULL;
        _len = 0;
        _total_MyString++;
    }

    // init with defined string
    MyString(const char *s):MyString(){
        (*this)= s;
    }

    // init with same class data
    MyString(const MyString & s):MyString(s._data){}

    // finalizer
    ~MyString(){
        _total_MyString--;
        delete _data;
    }

/////////////////////////////////////////////////////////
    static int total_MyString(){
        return _total_MyString;
    }
/////////////////////////////////////////////////////////
    char* data()const{
        return _data;
    }
/////////////////////////////////////////////////////////

    MyString& operator=(const char* &rhs){
        char* temp = const_cast<char*>(rhs);
        _len  = strlen(temp);
        _data = new char [_len + 1];
        strcpy(_data, rhs);
        return (*this);
    }

    MyString& operator=(const MyString& rhs){
        const char* temp = rhs._data;
        return (*this = temp);
    }

/////////////////////////////////////////////////////////
    MyString& operator+=(const char* &rhs){
        _len += strlen(rhs);
        strcat(_data, rhs);
        return *this;
    }

    MyString& operator+=(const MyString& rhs){
        const char* temp = rhs._data;
        (*this) += temp;
        return *this;
    }

/////////////////////////////////////////////////////////
    inline char & operator[](const int pos){
        return _data[pos];
    }

/////////////////////////////////////////////////////////
    unsigned length() const{
        return _len;
    }

/////////////////////////////////////////////////////////
    friend ostream &operator<<( ostream&, const MyString & );
    friend istream &operator>>( istream&, MyString & );
/////////////////////////////////////////////////////////
    bool operator==(const MyString& str){
        return !strcmp(_data, str._data);
    }

    friend bool operator!=(const MyString& str, const MyString& str2){
        return strcmp(str._data, str2._data) != 0;
    }
};

ostream& operator <<(ostream& os, const MyString& str){
    os << str.data();
    return os;
}

istream& operator >>(istream& is, MyString& str){
    char buffer[0xff];
    is.getline(buffer, 0xff);
    const char* temp = &buffer[0];
    str = temp;
    return is;
}

MyString.cpp

#include "MyString.h"

using namespace std ;

int MyString::_total_MyString = 0;

int  main()
{

    MyString Dstr1("String"), Dstr2("Test String 2"), Dstr3(Dstr1);

    cout << "Dstr1 is: " << Dstr1 << endl;
    cout << "Dstr2 is: " << Dstr2 << endl;
    cout << "Dstr3 is: " << Dstr3 << endl;
    cout << "Total MyString_Derived is: " << MyString_Derived::total_MyString() << endl;

/////////////////////////////////////////////////////////

    cout << "Give one word "<< endl;
    cin >> Dstr1;
    cout << "Dstr1 is: " << Dstr1 << endl;

/////////////////////////////////////////////////////////

    Dstr2 = Dstr1;
    cout << "Dstr2 is: " << Dstr2 << endl;
    return 0;
/////////////////////////////////////////////////////////

    Dstr3 += Dstr1;
    cout << "Dstr3 is: " << Dstr3 << endl;

/////////////////////////////////////////////////////////

    cout << "Dstr3 is: ";
    for(int i = 0; i<Dstr3.length(); i++)
        cout << Dstr3[i];
    cout << endl;

    for(int i = 0; i<Dstr3.length(); i++)
        Dstr3[i] = 'a' + i;
    cout << "Dstr3 is: " << Dstr3 << endl;

/////////////////////////////////////////////////////////

    cout << "Dstr1 is: " << Dstr1 << endl;
    cout << "Dstr2 is: " << Dstr2 << endl;
    cout << "Dstr3 is: " << Dstr3 << endl;
    cout << "Compare Dstr1 == Dstr2 is: " << (Dstr1 == Dstr2) << endl;
    cout << "Compare Dstr1 == Dstr3 is: " << (Dstr1 == Dstr3) << endl;
    cout << "Compare Dstr1 != Dstr2 is: " << (Dstr1 != Dstr2) << endl;
    cout << "Compare Dstr1 != Dstr3 is: " << (Dstr1 != Dstr3) << endl;
}

【问题讨论】:

  • 这可能不是导致此问题的原因,但您的 operator = 声称返回引用,但他们没有。这是 UB。
  • 可能是自分配的原因?见here。
  • 你的代码也不能编译,它应该是MyString&amp; operator=(const char* const &amp;rhs)。这是否是一个好主意是另一个话题。
  • 这不足以重现问题。类构造函数是什么样的?此外,operator= 需要制作源数据的副本,但它没有这样做,因此 operaror&gt;&gt; 中存在未定义的行为,这是由错误的 operator= 实现引起的。
  • 您的赋值运算符正在存储具有自动持续时间的对象的地址。在&gt;&gt; 返回后取消引用该指针是未定义的。 (这个练习主要是关于动态内存分配和指针体验。复习你的书和笔记。)

标签: c++


【解决方案1】:

考虑operator&gt;&gt;

istream& operator >>(istream& is, MyString& str){
    char buffer[0xff];
    is.getline(buffer, 0xff);
    const char* temp = &buffer[0];
    str = temp;
    return is;
}

buffer 是一个局部变量。您创建一个指向此本地数组的指针并将其分配给str。那叫

MyString& operator=(const char* &rhs){
    _data = const_cast<char*>(rhs);
    _len  = strlen(_data);
    return (*this);
}

有趣的是:作为参数,您将引用指向一个指针,即const,然后您从中剥离 const-ness 并将其分配给 _data。 现在char* _data 指向本地数组buffer。当本地数组被销毁时,函数结束时会发生什么?指针失效。

你需要实现一个深拷贝。

【讨论】:

  • 感谢您的回答!我只是用一些 C 字符串操作函数修复了它们。
猜你喜欢
  • 2012-05-30
  • 2021-12-16
  • 2020-05-30
  • 2013-10-10
  • 2011-09-23
  • 2015-07-03
  • 1970-01-01
  • 2014-04-10
  • 2013-12-20
相关资源
最近更新 更多