重载+=操作符,意外结果



为了学习,我自己写了一个字符串类。我试图重载+=运算符,这样我就可以把字符串附加在一起。但无论何时使用运算符,初始对象都保持不变。我很困惑。

StringF& StringF::operator+=(StringF& obj) {
const char* string = this->getString();
const char* stringToAppend = obj.getString();
const int stringLength = this->length();
const int stringToAppendLength = obj.length();
char* appendedString = new char[stringLength + stringToAppendLength];
appendedString[stringLength + stringToAppendLength] = '';

for (int i = 0; i < stringLength; i++) {
appendedString[i] = string[i];
}
for (int i = stringLength; i < stringLength + stringToAppendLength; i++) {
appendedString[i] = stringToAppend[i - stringLength];
}
StringF appendedObj = StringF::StringF(appendedString);
std::cout << "Appended obj: " << appendedObj.getString() << std::endl; //For debugging
return appendedObj;
}

这是类头文件:

class StringF {
private:
const char* string;
public:
StringF(const char*);
int length();
const char* copy();
const char* getString();
const char* reverse();
int find(const char*);
StringF& operator+=(StringF&);
friend std::ostream& operator<<(std::ostream&, StringF&);
};

我希望能够创建两个字符串并相互追加。但是它不起作用。什么好主意吗?如果可能的话,我想要一个解释,为什么这不起作用,这样我就可以试着自己弄清楚,因为我正在努力学习,我不想把解决方案交给我。但我什么都要。

这就是我要做的。

StringF s("Hello");
StringF s2(", World!");
s += s2;
std::cout << s << std::endl; //Should print "Hello, World!" but only prints "Hello".

提前感谢!

编辑:这是你尝试的例子。https://onlinegdb.com/ApfkIONXG

发布的代码有几个问题:

  1. 缓冲区溢出
  2. 您没有像operator+=那样修改this实例
  3. 您正在返回对本地
  4. 的引用。

下面是一些修复这些问题的最小编辑代码

StringF& StringF::operator+=(StringF& obj) {
const char* string = this->getString();
const char* stringToAppend = obj.getString();
const int stringLength = this->length();
const int stringToAppendLength = obj.length();
// +1 for the null character we are appending
char* appendedString = new char[stringLength + stringToAppendLength + 1];
appendedString[stringLength + stringToAppendLength] = '';

for (int i = 0; i < stringLength; i++) {
appendedString[i] = string[i];
}
for (int i = stringLength; i < stringLength + stringToAppendLength; i++) {
appendedString[i] = stringToAppend[i - stringLength];
}
// TODO: de-allocate the previous 'string' member variable
// Now we need to update `this`. While we can't modify the data pointed
// at by the existing member pointer, we can change the pointer to point
// to the newly allocated data:
string = appendedString;
// operator+= should be returning a reference to `this`
return *this;
}

可以修改成员变量,因为const char*是一个指向常量字符的可变指针。这意味着指针地址处的字符是不变的,但存储指针地址的内存仍然是可变的。

|string: 0xDEADBEEF|           // The pointer value is not const
|
|----> |abc|     // This data is const

参见Const before或Const after?有关const问题的更多信息。

return *this是因为operator+=的一般期望是以下代码应该工作:

StringF s1("a");
StringF s2("b");
StringF s3 = (s += s2);
assert(s3 == s);

在这个简单的示例中,这可能看起来像是无意义的代码,但是这种模式在某些情况下是有用的,并且是operator+=重载的预期行为。