我很困惑,因为我无法弄清楚我的错误/问题在哪里。 我有一个类指令,它使用两个自定义运算符,一个赋值和一个比较运算符。 以前我只使用比较运算符来使用std :: sort根据其成员之一对std :: string名称进行排序。 但是,自从我开始重新考虑整个项目因素后,我将一些成员更改为常量。这导致我不得不为这些常量使用初始化列表。 这反过来导致我必须创建一个赋值运算符,因为这些指令在向量中被推回时被复制。 这是一切都出错的地方。 我包括我的类声明和构造函数和操作符。
instruction.hpp
class Instruction
{
private:
unsigned int param_size;
const float max_angle, min_angle;
bool micro_mutated;
protected:
const std::string body_part;
std::vector<Parameter <float> > parameters;
public:
Instruction(std::string name, float max, float min);
Instruction operator=(const Instruction& I);
bool operator<(const Instruction& I) const;
//there are a few more functions but are completely irrelevant
}
instruction.cpp:
Instruction::Instruction(std::string name,float max, float min) :
body_part (name), max_angle(max), min_angle(min)
{}
Instruction Instruction::operator=(const Instruction& I)
{
(*this) = I;
return (*this);
}
bool Instruction::operator<(const Instruction& I) const
{
return body_part < I.body_part;
}
我创建一个赋值运算符(说实话我以前从未做过)的唯一原因是因为当我尝试push_back指令时,编译器抱怨无法实例化“从这里”指令并且我想它与常数成员有关。如果成员不变,一切都很好,甚至排序。 现在奇怪的部分。如果我删除std :: sort,上面的代码可以工作,但不是所有的时间。有时候它会在一段时间后崩溃,有时会不会崩溃。但是当我包括排序时,它会立即崩溃。 有人可以帮忙吗?
答案 0 :(得分:2)
不要忘记三个规则:如果你有一个复制构造,复制赋值运算符和析构函数,那么你应该所有。
但是,您的复制赋值运算符实际上是一个无限循环;它自称。只要您有任何形式的Instruction &=Instruction&
,就会使用Operator =。这正是(*this) = I
的原因。
我的问题是:为什么这些事情不变?让成员保持有效意味着你不能复制对象(除非你使用const-cast)复制赋值。你可以复制构造它们,但那就是它。
这些成员有什么理由保持不变吗?如果是这样,那么你不应该通过赋值复制这些对象。这两者是相互排斥的。
如果你需要一个成员有效地保持不变,不能通过外部活动(但不能语言 -const来阻止复制),那么这应该通过适当的访问器方法来完成。为类的用户提供获取这些值的方法,但不提供设置它们的方法。