【发布时间】:2011-01-26 16:11:20
【问题描述】:
我有一个类(读过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);
函数calculator() 使用这种类型的对象。作为函数的一部分,使用库的通用排序函数对(已声明的)Student_info 对象的向量进行排序。我的程序没有超过这一点(尽管根据 NetBeans 没有抛出异常并且程序正确退出)。
排序函数大量使用容器中保存的任何类型的赋值运算符,但我似乎无法找出我定义的那个有什么问题(程序在我定义它之前运行正常)。根据 Accelerated C++(或者至少我是这样解释的),赋值运算符应该工作的正确方式是首先破坏左操作数,然后用等于右操作数的值再次构造它。所以这是我重载的 operator= 定义:
Student_info& Student_info::operator=(const Student_info& s)
{
if(this != &s)
{
this->~Student_info();
destroyCount++;
*this = s;
}
return *this;
}
如您所见,它调用了 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++;
}
复制构造函数正确运行,因为省略排序语句允许程序正确运行并产生大于 0 的 copyCount(仅在复制构造函数和 operator= 中修改)。
那么我的赋值运算符到底出了什么问题?它与调用 Student_info 对象的破坏有关,但我不知道如何纠正它,除非不破坏它。
(顺便说一句,Accelerated C++ 中的一个练习要求创建复制构造函数、析构函数和赋值运算符……我意识到这些函数的合成版本显然足以满足我的课程)
【问题讨论】:
-
"根据 Accelerated C++ ..." -- 章节和诗句好吗?我想看看它到底说了什么误导了你。
-
当然。它在第 11 章,特别是 11.3.3 “赋值不是初始化”。它是该小节中的第二段,内容如下:“关键区别源于两个观察结果:赋值 (operator=) 总是消除先前的值;初始化永远不会这样做。”然后继续给出使用“=”导致初始化的代码示例,以及导致赋值的代码示例。所以换句话说,使用“=”的上下文决定了是初始化还是赋值。
-
@Kevin:这种差异是语法上的。这是
int a = 10;和int a; a = 10;之间的区别,与如何实现operator=无关——也就是说,int a = 10;将成为复制构造函数调用,而不是赋值运算符调用。在重载operator=时,您不需要知道或理解这种差异。至于p197上的代码样例,因为我没有副本,所以我无法定义它是对还是错,虽然如果它提倡destruct-and-copy-construct模式,那肯定是不正确的。 -
您会注意到使用了 obliterate 这个词而不是 destroy。虽然我没有亲自问过他们,但我敢打赌安德鲁和芭芭拉故意避免使用破坏这个词,因为它太接近于破坏者这个词。他们只是说有一个先前的值,而您正在删除该值并用另一个值替换它。这与初始化形成对比,初始化不会替换预先存在的值。通常,这种区别是微不足道的。例如删除一个 int 的先前值并用一个新值替换它需要完全相同的操作。
-
我认为这个类根本不需要用户定义的拷贝构造函数、拷贝赋值运算符和析构函数,类不管理资源,自动生成的特殊成员函数完全美好的。您还希望第二个构造函数是显式的。
标签: c++ sorting copy-constructor assignment-operator