Kev*_*vin 2 c++ sorting copy-constructor assignment-operator
我有一个类(那些已经读过Accelerated C++的人可能会发现这个类很熟悉)定义如下:
class Student_info{
public:
Student_info() : midterm(0.0), final(0.0) {};
Student_info(std::istream& is){read(is);};
Student_info(const Student_info& s);
~Student_info();
Student_info& operator=(const Student_info& s);
//Getters, setters, and other member functions ommited for brevity
static int assignCount;
static int copyCount;
static int destroyCount;
private:
std::string name;
double midterm;
double final;
double finalGrade;
std::vector<double> homework;
};
typedef std::vector<Student_info> stuContainer;
bool compare(const Student_info& x, const Student_info& y);
Run Code Online (Sandbox Code Playgroud)
函数calculator()使用这种类型的对象.作为函数的一部分,使用库的通用排序函数对(已声明的)Student_info对象的向量进行排序.我的程序没有超过这一点(尽管根据NetBeans没有抛出任何异常并且程序正确退出).
sort函数大量使用容器中保存的任何类型的赋值运算符,但我似乎无法找出我定义的那个错误(程序在我定义之前正常运行).根据Accelerated C++(或至少这是我解释它的方式),赋值运算符应该工作的正确方法是首先销毁左操作数,然后使用等于右操作数的值再次构造它.所以这是我的重载operator =定义:
Student_info& Student_info::operator=(const Student_info& s)
{
if(this != &s)
{
this->~Student_info();
destroyCount++;
*this = s;
}
return *this;
}
Run Code Online (Sandbox Code Playgroud)
如您所见,它调用Student_info复制构造函数,该构造函数定义如下:
Student_info::Student_info(const Student_info& s)
{
name = s.name;
midterm = s.midterm;
final = s.final;
finalGrade = s.finalGrade;
homework = s.homework;
copyCount++;
}
Run Code Online (Sandbox Code Playgroud)
复制构造函数正常运行,因为省略sort语句允许程序正常运行并产生大于0的copyCount(仅在复制构造函数和operator =中修改).
那么我的赋值运算符究竟出了什么问题呢?它与调用Student_info对象的破坏有关,但我不知道如何纠正它而不是破坏它.
(顺便说一下,复制构造函数,析构函数和赋值运算符的创建是通过Accelerated C++中的练习调用的......我意识到这些函数的合成版本显然足以满足我的类)
不不不.根本不应该那样工作.你当前的赋值运算符会破坏它所调用的对象,然后在被破坏的对象上调用自己(哦,嘿,无限递归)(哦,嘿,未定义的行为).你不应该破坏现有的对象.完全没有.并且这段代码*this = s根本不会调用任何构造函数,它会调用赋值运算符 - 这就是您刚才定义的.复制构造函数调用看起来像new (this) Student_info(s);.这是一种已知的模式,它在许多方面都很糟糕.如果您有一本推荐它的书,请将其扔进垃圾箱.
赋值运算符应该将数据从右侧复制到左侧.在大多数情况下,最简单的方法就是复制每个数据成员.此运算符的语义不涉及破坏任何内容.任何使用此运算符的人都有权期望不会破坏正在进行的任何Student_info对象.
只需调用成员的现有赋值运算符,然后实现所需的任何其他逻辑.
| 归档时间: |
|
| 查看次数: |
721 次 |
| 最近记录: |