请考虑以下代码:
class CString
{
private:
char* buff;
size_t len;
public:
CString(const char* p):len(0), buff(nullptr)
{
cout << "Constructor called!"<<endl;
if (p!=nullptr)
{
len= strlen(p);
if (len>0)
{
buff= new char[len+1];
strcpy_s(buff, len+1, p);
}
}
}
CString (const CString& s)
{
cout << "Copy constructor called!"<<endl;
len= s.len;
buff= new char[len+1];
strcpy_s(buff, len+1, s.buff);
}
CString& operator = (const CString& rhs)
{
cout << "Assignment operator called!"<<endl;
if (this != &rhs)
{
len= rhs.len;
delete[] buff;
buff= new char[len+1];
strcpy_s(buff, len+1, rhs.buff);
}
return *this;
}
CString operator + (const CString& rhs) const
{
cout << "Addition operator called!"<<endl;
size_t lenght= len+rhs.len+1;
char* tmp = new char[lenght];
strcpy_s(tmp, lenght, buff);
strcat_s(tmp, lenght, rhs.buff);
return CString(tmp);
}
~CString()
{
cout << "Destructor called!"<<endl;
delete[] buff;
}
};
int main()
{
CString s1("Hello");
CString s2("World");
CString s3 = s1+s2;
}
我的问题是我不知道如何删除在加法运算符函数(char* tmp = new char[length]
)中分配的内存。我无法在构造函数中执行此操作(我尝试delete[] p
),因为它也是从main函数调用的,其中chars数组作为参数未在堆上分配...我如何解决这个问题?
答案 0 :(得分:4)
添加函数应返回CString,而不是CString&amp;。在添加函数中,你应该构造返回值,然后删除不再需要的[] temp,因为在CString类中你可以创建一个内存副本。
CString operator + (const CString& rhs) const
{
cout << "Addition operator called!"<<endl;
size_t lenght= len+rhs.len+1;
char* tmp = new char[lenght];
strcpy_s(tmp, lenght, buff);
strcat_s(tmp, lenght, rhs.buff);
CString retval(tmp);
delete[] tmp;
return retval;
}
答案 1 :(得分:2)
问题:
在您的赋值运算符中,您未能提供任何异常保证。在确保操作成功之前,您正在删除缓冲区。如果出现问题,您的对象将处于未定义状态。
CString& operator = (const CString& rhs)
{
cout << "Assignment operator called!"<<endl;
if (this != &rhs)
{
len= rhs.len;
delete[] buff;
buff= new char[len+1]; /// BOOM
// If you throw here buff now points at undefined memory.
// If this is an automatic variable the destructor is still going
// to be called and you will get a double delete.
// All operations that can fail should be done BEFORE the object is modified.
strcpy_s(buff, len+1, rhs.buff);
}
return *this;
}
我们可以通过移动(并使用临时)来纠正这些问题。
CString& operator = (const CString& rhs)
{
cout << "Assignment operator called!"<<endl;
if (this != &rhs)
{
char* tmp = new char[len+1];
strcpy_s(tmp, rhs.len+1, rhs.buff); // for char this will never fail
// But if it was another type the copy
// may potentially fail. So you must
// do the copy before changing the curren
// objects state.
// Now we can change the state of the object safely.
len= rhs.len;
std::swap(tmp,buff);
delete tmp;
}
return *this;
}
更好的解决方案是使用复制和交换idium:
CString& operator = (CString rhs) // Note pass by value to get auto copy.
{ // Most compilers will then do NRVO
this->swap(rhs);
// Simply swap the tmp rhs with this.
// Note that tmp was created with copy constructor.
// When rhs goes out of scope it will delete the object.
}
void swap(CString& rhs)
{
std::swap(len, rhs.len);
std::swap(buff, rhs.buff);
}
现在让我们处理您的+运算符
CString operator + (const CString& rhs) const
{
// You could optimize this by providing a private constructor
// that takes two char pointers so that allocation is only done
// once.
CString result(*this);
return result += rhs;
}
CString operator += (const CString& rhs)
{
size_t lenght= len+rhs.len+1;
// Char are easy. No chance of failure.
// But if this was a type with a copy constructor or any other complex
// processing involved in the copy then I would make tmp a smart pointer
// to make sure that it's memory was not leaked if there was an exception.
char* tmp = new char[lenght];
strcpy_s(tmp, lenght, buff);
strcat_s(tmp, lenght, rhs.buff);
std::swap(len, length);
std::swap(buff, tmp);
delete tmp;
}
答案 2 :(得分:0)
CString& operator + (const CString& rhs) const
{
cout << "Addition operator called!"<<endl;
size_t lenght= len+rhs.len+1;
char* tmp = new char[lenght];
strcpy_s(tmp, lenght, buff);
strcat_s(tmp, lenght, rhs.buff);
CString tempObj(tmp);
delete [] tmp;
return tempObj;
}
例如,
答案 3 :(得分:0)
首先,operator+
应返回新对象,而不是修改+
的操作数之一,因此最好将其声明为非成员(可能是朋友)函数。首先实现operator+=
然后使用它 - operator+
,你就不会遇到这个问题。
CString operator+(CString const& lh, CString const& rh)
{
CString res(lh);
return res += rh;
}