我想问一些问题。我正在我的教师中学习OOP C ++课程。我们通过重新初始化动态分配的char数组进行了一些练习。问题如下:
class state
{
private:
char *szstate; // a name of object
public:
state &operator = (const state&);
};
state & state::operator = (const state &cop)
{
if (this != &cop)
{
szstate = new char [strlen(cop.szstate)+strlen("==.")+1];
strcpy(this->szstate,"==.");
strcat(this->szstate, cop.szstate);
return *this;
}
else return *this;
}
在快捷方式中,创建一个名为“DEFAULT”的对象“a”,在b = a之后,应该给我一个名为“==。DEFAULT”的对象b。这将需要更多的内存,所以我使用operator new来保证安全。 问题是老师说应该也有
delete []szstate
在我重新初始化对象的“名称”之前 - 我试过这个,但出现了分段错误。无论如何,我在斯蒂芬普拉塔的书中找到了一些写作,在那里他写道,char *将保持不变; char *应被视为不可更改的常量,因此将对错误进行某种解释。那么,我做错了什么还是老师没有权利? 谢谢你的答案:)
答案 0 :(得分:3)
szstate
的初始值是多少?
你应该阅读有关三条规则的内容。基本上,如果你 需要手工编写任意三个函数的复制构造函数, 赋值和析构函数,你可能要编写所有的 他们。并且还有一些非平凡的构造函数。在你的 情况下:
您显然需要构造函数,以确保szstate
始终初始化为定义的值。 (取决于
逻辑,空指针可能没问题。)
您还需要一个析构函数,以确保任何动态
szstate
指向的已分配内存已正确释放。
在赋值运算符中,您必须确保永远不会 如果存在异常,则将对象保持无效状态。
这样做的经典方法是:
class State
{
char* myState;
public:
State()
: myState( new char[1] )
{
myState[0] = '\0';
}
State( State const& other )
: myState( new char[ strlen( other.myState ) + 1 ] )
{
strcpy( myState, other.myState );
}
~State()
{
delete[] myState;
}
State& operator=( State const& other )
{
char const* tmp = new char[ strlen( other.myState) + 1 ];
strcpy( tmp, other.myState );
delete myState;
myState = tmp;
return *this;
}
};
这实现了纯粹的深层复制语义,但它应该给你 表明你需要做什么。
另外:没有必要检查自我分配 赋值运算符。需要进行此类检查通常是一个标志 你做错了什么,如果有的话就不安全 是例外。
答案 1 :(得分:1)
您应该将构造函数添加到状态类并在其中初始化szstate为nullptr(或0),然后在您的operator = new char
调用之前
delete[] szstate; // edit, no need to check szstate if its null (standard allows it)
这样你就不会出现分段错误
char *将保持不变; char *应视为不可更改 常数,这将是对错误的某种解释。
也许你的意思是字符串文字(const char [])?你不应该删除它们,但是你有动态数组,一旦它不再需要就应该被删除,或者你要通过为它分配新分配的数组来松散指向它的指针。