复合赋值和添加运算符重载
Compound assignment and add operator overloading
我需要下面介绍的两个运算符重载函数的帮助。我不确定如何在不实际使用函数定义中的赋值的情况下实现这一点。
我的.cpp文件中运算符 + 的代码:
MyString& MyString::operator +(const MyString& rhs)
{
delete [] String;
String = new char[rhs.Size];
Size = rhs.Size;
// needs to be a loop for cascading +
// so that String1=String2+String3+String4 will work
for(int i = 0; i < rhs.Size+1 ; i++)
{
// String[i] + rhs.String[i]; ???
}
return *this;
}
.cpp文件中 += 运算符的代码:
MyString& MyString::operator+=(const MyString& rhs)
{
delete [] String;
String = new char[rhs.Size];
String = String + rhs.String;
return *this;
}
主.cpp呼叫:
String1 = String2 + String3 + String4;
String1.Print ();
String2 += String3;
String2.Print ();
我知道我的.cpp文件代码是错误的,一些见解会很棒!
惯用的方法是在operator+=
中实现功能,然后使用它来实现operator+
。假设对于初学者来说,你的operator+=
被正确实现,那么operator+
作为一个自由函数是可以简单实现的:
MyString operator+( MyString lhs, MyString const & rhs ) {
lhs += rhs;
return lhs;
}
注意:第一个参数是按值传递的,因此它是原始参数的副本,我们可以通过 operator+=
.这里还有其他一些提示可能会对您有用。
现在回到实现operator+=
,您应该了解的第一件事是您需要执行的操作是什么:您需要分配更长的缓冲区,从旧缓冲区复制,附加rhs
字符串,交换旧缓冲区和新缓冲区(包含结果(并释放旧缓冲区。操作的顺序很重要,如果您在复制之前释放旧内容(就像您正在做的那样(,那么您就不能再从中复制。
// Rough approach
MyString& operator+=( MyString const & rhs ) {
char * new_buffer = new char[ Size + rhs.size + 1]; // [1]
std::copy_n( String, Size, new_buffer );
std::copy_n( rhs.String, rhs.Size + 1, new_buffer+Size ); // [2]
swap(String, new_buffer); // [3]
Size = Size + rhs.Size;
delete [] new_buffer;
return *this;
}
[1]:分配新的缓冲区并复制到其中。请注意,在这种特殊情况下,代码是正确的,因为函数中的其余指令都不会引发异常。如果不是这种情况,则应通过 RAII 管理新缓冲区,以确保至少最小的异常安全性。
[2]:假设作为类型MyString
的不变量,始终存在一个空终止符。count 参数中的Size+1
将复制所有元素和 null 终止符。
[3]:此时所有操作都已经执行完毕,我们可以交换新旧缓冲区,更新大小和释放new_buffer
(实际上指的是旧的缓冲区(
首先,通常你从 operator+
返回一个新对象,因为期望在对象上调用 + 不会改变对象本身。
MyString MyString::operator+ (const MyString& rhs)
{
// ...
return MyString(...);
}
请注意返回类型中缺少的引用 ( &
(:您返回的是按副本返回新对象,而不是按引用。
其次,如果您在开始时delete
String
,您将无法复制其内容。 考虑一下operator+
:
char* tmp = new char[Size + rhs.Size + 1]; // +1 for the terminating ' '
for(int i = 0; i < Size ; i++)
{
// copy the contents of current object buffer, char-by-char
tmp[i] = String[i];
}
for(int i = 0; i < rhs.Size+1; i++) // +1 to copy the terminating ' ' as well
{
// copy the contents of other object buffer, char-by-char
tmp[i+Size] = rhs.String[i];
}
MyString result;
delete[] result.String;
result.String = tmp;
result.Size = Size+rhs.Size;
return result;
operator+=
有点棘手,因为您需要操作当前对象的缓冲区:
char* tmp = new char[Size + rhs.Size + 1]; // +1 for the terminating ' '
for(int i = 0; i < Size ; i++)
{
tmp[i] = String[i];
}
for(int i = 0; i < rhs.Size+1; i++) // +1 to copy the terminating ' ' as well
{
tmp[i+Size] = rhs.String[i];
}
delete[] String;
String = tmp;
Size += rhs.Size;
return *this;
更新:我假设您还在类析构函数中调用delete[]
- 您应该这样做。 也不难想象,你会想要从一个MyString
对象到另一个对象执行断言。 这将导致三法则:如果你需要desgtructor,copy-constructor或赋值运算符中的任何一个,你很可能需要这三个
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么这个运算符<重载函数对 STL 算法不可见?
- <T> 通过模板化运算符重载将 std::complex 乘以双倍
- C++20概念:需要运算符重载
- 使用赋值运算符重载从类中返回jobject
- 在运算符重载定义中使用成员函数(const错误)
- 字节到位运算符重载C++
- 为什么在运算符重载时需要参考?
- 类中 c++ 的运算符 + 重载
- 算术复合运算符重载为非成员
- 运算符重载 (+),用于添加两个具有 C++ 的数组
- 交换运算符 + 重载会导致无限递归
- 如何理解新的运算符重载?
- 向量保持复数的运算符重载
- 如何创建运算符重载?
- 链接列表运算符重载没有打印出我想要的内容
- C++:需要帮助了解运算符重载错误
- 使用模板化运算符重载 XOR 运算符失败
- 如何确保接受的C++模板类型使运算符重载?
- 运算符重载使用运算符+添加类模板