1
class String
{
    char* array;
public:
    String(const char* s)
    {
        array = new char[strlen(s) + 1]{ '\0' };
        strcpy(array, s);
    }
    ~String()
    {
        if (array)
        {
            delete[]array;
        }
    }
    String operator+ (const char* p)   //返回对象
    {
        String temp(p);
        char* tempStr = temp.array;
        temp.array = new char[strlen(array) + strlen(tempStr) + 1]{ '\0' };
        strcpy(temp.array, array);
        strcat(temp.array, p);
        delete[]tempStr;
        return temp;
    }
    friend ostream& operator<<(ostream& output, String& x);   // <<函数重载只能定义成友元
};

ostream& operator << (ostream& output, String& x)  //对<<重载的方式
{
    output << x.array;
    return output;
}

int main()
{
    String string1("mystring");
    cout << string1 + "ab" << endl;
    cout << string1 << endl;
    return 0;
}

This is my first time asking a question here, so please forgive me if there are any bad descriptions :)

Back to the point ,I have overloaded + and << operators,so I want to get the output "mystringab" by cout<<string1+"ab"<<endl,but the output is garbled.

I think there may be a problem with the + operator overloaded function,can someone please tell me where is the problem?

And if I want to get the correct result, how should I rewrite the overloaded function?

Mr Right
  • 35
  • 4
  • Make the second parameter of `operator<<` a `const String&`. – Jason May 11 '22 at 17:11
  • Thanks, but I just tried it and it still seems to output garbled characters :( – Mr Right May 11 '22 at 17:22
  • See my answer below and this [working demo](https://onlinegdb.com/2XX1CNnxD). Also don't forget to make sure that you don't have any undefined behavior in your program. – Jason May 11 '22 at 17:23
  • Thank you very much for your answer :) I am learning object-oriented programming so I am not very clear about some mechanisms – Mr Right May 11 '22 at 17:30
  • I'll take a closer look later – Mr Right May 11 '22 at 17:39
  • `delete[]tempStr;` right before `return temp;` frees the buffer [owned](https://stackoverflow.com/questions/49024982/what-is-ownership-of-resources-or-pointers) by temp. This is fatal. – user4581301 May 11 '22 at 17:39
  • `String` does not observe [the rule of three or friends](https://en.cppreference.com/w/cpp/language/rule_of_three). This means it cannot be copied safely. Passing or returning by value will make copies. `String operator+ (const char* p)` returns by value, makes a copy and thus will be fatal. – user4581301 May 11 '22 at 17:41
  • Some good reading: [What are the basic rules and idioms for operator overloading?](https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading) – user4581301 May 11 '22 at 17:43
  • how should I rewrite the overloaded function by value – Mr Right May 11 '22 at 17:46
  • Tactical note: If you add a book-keeping variable to track the length of the string, you can save yourself the costs of calling `strlen` over and over. – user4581301 May 11 '22 at 17:46
  • You need to return by value from `operator+`, this means you must make `String` copyable (or rewrite to ensure elision, but a copyable class is much more useful than one that will fail if copied). Read the posted link about [the Rule of Three](https://en.cppreference.com/w/cpp/language/rule_of_three). – user4581301 May 11 '22 at 17:52
  • I suggest asking a second question that specifically deals with improving `operator+` because Stack Overflow is at it's best when it deals with one problem per question. There are very important suggestions in the posted link [What are the basic rules and idioms for operator overloading?](https://stackoverflow.com/questions/4421706/) that may eliminate the need for this question, though. – user4581301 May 11 '22 at 17:53
  • I thought about it for a few hours and finally I know where I went wrong. When `temp` is returned, the copy constructor written by the compiler itself will be called to make a `shallow copy`, thereby creating an anonymous object, the `char *array` of this anonymous object and `temp.array` point to the same address, so when the function ends and `temp` is destructed, the `char *array` of the anonymous object is also deleted, so garbled characters will be output. The solution is to define a copy constructor by yourself to make a deep copy – Mr Right May 11 '22 at 22:12

1 Answers1

0

The problem is that the second parameter to overloaded operator<< cannot be bound to an String rvalue since the second parameter is an lvalue reference to a non-const String.

how should I rewrite the overloaded function?

You need to make the second parameter to overloaded operator<< a const String& so that it can work with the second argument "ab" as well, as shown below:

//---------------------------------------- vvvvv------------>low-level const added here
friend ostream& operator<<(ostream& output,const String& x);

Similarly do the same in the definition:

//----------------------------------- vvvvv------------>low-level const added here
ostream& operator << (ostream& output,const String& x) 
{
    output << x.array;
    return output;
}

Also, make sure that your program don't have any undefined behavior. For example, by making sure that you use delete or delete[] only when it is safe to do so(that data to which the pointer points is no longer needed). You can use tools such as valgrind to detect some basic problems.

Jason
  • 36,170
  • 5
  • 26
  • 60