0

我很困惑,因为我无法弄清楚我的错误/问题在哪里。我有一个类指令,它使用两个自定义运算符,一个赋值和一个比较运算符。以前我只使用比较运算符,以便使用 std::sort 根据指令的成员之一(即 std::string 名称)对指令进行排序。但是,自从我开始重构整个项目后,我将一些成员更改为常量。这导致我不得不为这些常量使用初始化列表。这反过来又导致我不得不创建一个赋值运算符,因为这些指令在向量中推回时会被复制。这就是一切出错的地方。我包括我的类声明和构造函数和运算符。

指令.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
}

指令.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,上面的代码可以工作,但不是一直有效。有时它会在一段时间后崩溃,有时它不会崩溃。但是在我包括排序的那一刻,它会立即崩溃。有人可以帮忙吗?

4

1 回答 1

2

不要忘记三原则:如果您有复制构造、复制赋值运算符和析构函数之一,那么您应该拥有所有这些。

但是,您的复制赋值运算符实际上是一个无限循环;它自称。只要您有以下形式的任何内容,都会使用 Operator=:Instruction &=Instruction&。这正是(*this) = I

我的问题是:为什么这些事情是不变的?让成员有效地保持不变意味着您不能通过复制分配复制对象(除非您使用 const-cast)。您可以复制构建它们,但仅此而已。

这些成员保持不变有什么理由吗?如果是这样,那么您不应该通过分配复制这些对象。两者是互斥的。

如果您需要一个成员有效地保持不变,不受外部活动的影响(但不是语言-const 防止复制),那么这应该使用适当的访问器方法来完成。为类的用户提供获取这些值的方法,而不是设置它们的方法。

于 2011-07-02T23:13:31.627 回答