为什么在进行复制赋值之前调用复制构造函数
why is the copy constructor being called before copy assignment?
class LinkedList
{
public:
LinkedList() : _head(nullptr) {}
LinkedList(ListElement *newElement) : _head(newElement) {}
~LinkedList() { };
LinkedList(const LinkedList& LL);
LinkedList& operator=(LinkedList byValLinkedList);
private:
ListElement *_head;
}
LinkedList::LinkedList(const LinkedList & LL)
{
ListElement *curr = LL._head;
// If Linked List is empty
if (isEmpty() && curr != nullptr) {
_head = new ListElement(curr->getValue());
curr = curr->getNext();
}
ListElement *newNode = nullptr;
while (curr) {
newNode = new ListElement(curr->getValue());
curr = curr->getNext();
}
}
LinkedList& LinkedList::operator=(LinkedList byValLinkedList)
{
std::swap(_head, byValLinkedList._head);
return *this;
}
int main() {
using namespace std;
LinkedList LL1(new ListElement(7));
//..... some insertions
LinkedList LL2(new ListElement(5));
//..... some insertions
LL1 = LL2; // What is the order ?
// ..... do something else
return 0;
}
当LL1=LL2被执行时,应该调用哪一个。
我希望能完成复印作业。但代码是按以下顺序执行的
- 复制构造函数
- 复制分配
- 破坏者
我做错了什么?为什么要调用析构函数
LinkedList& operator=(LinkedList byValLinkedList);
您的副本分配按值获取其参数。这意味着
LL1=LL2;
需要复制LL2
,以便按值传递。这就是";传递值";方法因此,复制构造函数。
为了避免复制构造,赋值运算符必须引用其参数,而不是:
LinkedList& operator=(const LinkedList &byValLinkedList);
这意味着,当然,如果您不能完全使用std::swap
实现赋值运算符。但这将是一个不同的问题。。。
简单地说,您有两个选项:要么实现两个复制构造函数,一个采用const
引用,另一个不采用,后者可以使用std::swap
。或者,将_head
声明为mutable
。
您没有做错任何事情,这正是复制和交换的工作方式。
复制构造函数被调用来设置参数,该参数由值传递。这很好,因为否则您的副本分配操作符将不得不包含用于制作副本的代码。通过这种方式,您可以重用复制构造函数中的逻辑。
然后,参数超出范围,并在函数结束时被销毁。由于交换调用,该参数现在包含*this
曾经拥有的资源。同样非常可取的是,因为析构函数负责释放它们——否则,您将不得不为复制赋值运算符编写清理代码,以正确地清除被赋值替换的数据。
除了代码重用之外,复制和交换还为您提供了异常安全性。如果您直接将副本复制到左侧对象(*this
)中,那么如果出现任何问题,则说明您已经丢失了旧值,无法保持不变。但是,使用复制和交换,复制构造函数首先完成它的工作——如果出现任何错误,例如内存不足,*this
将保留其以前的值。
这里对复制和交换习语有一个非常广泛的解释:
- 什么是复制和交换习语
在您的赋值运算符中,byVallinkedList是通过值传递的。LinkedList对象是通过使用复制构造函数初始化的
- 当从函数参数中的临时值调用复制构造函数时
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- 为什么默认复制函数在按值发送参数时不调用?
- 为什么调用复制构造函数而不是移动构造函数?
- C++ 基本 CTOR 说明 - 为什么不调用赋值/复制构造函数
- 为用户定义的类正确调用复制构造函数/赋值运算符
- 复制构造函数中的递归调用
- 编译器调用复制运算符而不是移动运算符
- 为什么我的运算符 + 重载尽管是通过引用传递的,但仍调用我的复制构造函数?
- 使用 pybind11 调用 Python 函数时避免复制输入数据
- 为什么没有调用此模板类的复制构造函数?
- 为什么当我做复制和交换习语时不调用我的复制构造函数?
- std::async 如何工作:为什么它会调用这么多次复制/移动?
- 调用类模板中隐式删除的复制构造函数
- 我不知道为什么复制构造函数的调用在 c++ 中不稳定
- push_back std::vector,则重复调用复制构造函数
- 减少复制构造函数调用
- 调用值构造函数而不是复制构造函数
- 向量<shared_ptr<X>>复制- 调用 X 构造函数?