提问人:TobyFromHR 提问时间:8/30/2023 更新时间:9/5/2023 访问量:75
试图找出课程类的复制构造函数
Trying to figure out a Copy Constructor for the course class
问:
这是有问题的课程类。
class Course {
//** You may not change the declarations in this private: area.
CourseName name; ///< Name of the course
int numberOfPrerequisites; ///< How many prereqs are currently in the array?
int maxPrerequisites; ///< How many prereqs will fit into the array?
CourseName * prereqs;
这是我目前所拥有的。请注意,此复制构造函数会导致我的一些单元测试失败。我无法更改单元测试,而是必须修复复制构造函数:
Course::Course(const Course& other)
: name(other.name), numberOfPrerequisites(other.numberOfPrerequisites),
maxPrerequisites(other.maxPrerequisites), prereqs(new CourseName[other.maxPrerequisites])
{
// Copy all prerequisites
for (int i = 0; i < numberOfPrerequisites; ++i)
{
prereqs[i] = other.prereqs[i];
}
}
失败的单元测试表示,一旦使用另一门课程初始化了新课程,当您修改新创建的课程时,它也会更改原始课程。简单地说,它们在修改后是相同的,而它们应该是不同的。
这些是我迄今为止尝试过的运算符重载。
bool Course::operator==(const Course& other) const
{
return name == other.name;
}
Course& Course::operator=(const Course& other)
{
if (this == &other)
return *this;
name = other.name;
numberOfPrerequisites = other.numberOfPrerequisites;
maxPrerequisites = other.maxPrerequisites;
delete[] prereqs;
prereqs = new CourseName[other.maxPrerequisites];
// Copy the prerequisites from the source object to the new object
for (int i = 0; i < numberOfPrerequisites; ++i)
{
prereqs[i] = other.prereqs[i];
}
return *this;
}
答:
这似乎是某种家庭作业,所以我不想在这个答案中透露太多。
也就是说,评论已经确定了这些事情:
- copy-ctor 似乎没问题。
- 复制分配也是如此。
operator=
- dtor 丢失。
- 平等是不足的。
operator==
缺少 dtor 将导致内存泄漏。但是,缺少它不应导致复制 ctor 或复制分配失败。operator=
失败的单元测试表明,一旦使用另一门课程初始化了新课程,当您修改新创建的课程时,它也会更改原始课程。
如果 copy-ctor 正确地完成了它的工作——这似乎是这种情况——那么唯一可能出错的就是复制 .CourseName
起初,我以为它有一个简单的定义,如下所示:
struct CourseName
{
std::string name;
bool operator== (CourseName const&) const = default;
};
但如果这是真的,那么复制器就不会有错误。
就在那时,我突然想到这是一堂关于深度复制和深度比较的课程。教师是否实施了“三法则”?CourseName
struct CourseName
{
char const* name_{ nullptr };
public:
CourseName(char const* name);
// Rule of Three
~CourseName();
CourseName(CourseName const& other);
CourseName& operator=(CourseName const& other);
// Other member functions and operators
bool operator== (CourseName const& other) const;
};
如果是这样,那么编译器提供的默认复制分配将不做正确的事情。进行成员比较的平等也不会。operator=
CourseName
operator==
因此,你的问题可能是你需要做更多的工作。CourseName
如果不是,那么我们将需要看到一个最小的、可重复的例子,以便进一步分析。那应该是一个完整的程序,包括功能。MRE 会排除不必要的细节,但会重现错误。main
什么是“强力保证”?
所谓“强保证”,就是当OR等算子失败时,原物不变的承诺。这是全有或全无:不允许部分更新。operator=
operator>>
原问题中给出的并不能提供强有力的保证。对 operator 的调用可能会失败,抛出 .发生这种情况时,您将无法恢复原始对象,因为您已经将其删除。operator=
new[]
std::bad_alloc
为了提供强有力的保证,您需要将运算符的结果分配给临时变量,并且仅在安全接收到该指针后才更新对象。new[]
这是你的,只需要很少的改变来提供强有力的保证。operator=
Course& Course::operator=(const Course& other)
{
if (this == &other)
return *this;
// If the call to operator new[] is going to fail,
// we need that to happen before we start deleting
// the original object. That is why we do this first.
auto temp = new CourseName[other.maxPrerequisites];
// Operator new[] did not throw std::bad_alloc.
// Now it is safe to start overwriting things.
name = other.name;
numberOfPrerequisites = other.numberOfPrerequisites;
maxPrerequisites = other.maxPrerequisites;
delete[] prereqs;
// Assign the temporary pointer created above.
prereqs = temp;
// Copy the prerequisites from the source object to the new object
for (int i = 0; i < numberOfPrerequisites; ++i)
{
prereqs[i] = other.prereqs[i];
}
return *this;
}
如评论中所述,复制和交换习语是实现 .复制和交换具有简单性的好处,此外,还提供了强有力的保证。operator=
评论
this->numberOfPrerequisites
other.numberOfPrerequisites
for (std::size_t i{}; < numberOfPrerequisites; ++i) ...
CourseName
operator==
CourseName
CourseName
评论
CourseName
CourseName * prereqs;
std::vector<CourseName> prereqs;
Course
CourseName
operator==
Course
maxPrerequisites
operator==