在深入研究之前,让我们先看看我们使用的普通“重载赋值运算符”。
null
// Simple C++ program to demonstrate overloading of // assignment operator. #include <iostream> #include <cstring> using namespace std; class anyArrayClass { int size; int *ptr; public : // Initializer list anyArrayClass( int s=0):size(s), ptr(size? new int [size]:nullptr) {} // Copy constructor anyArrayClass( const anyArrayClass& obj):size(obj.size), ptr(size? new int [size]:nullptr) { memmove (ptr, obj.ptr, size* sizeof ( int )); } // Overloaded assignment operator anyArrayClass& operator=( const anyArrayClass& obj) { // self assignment check if ( this != &obj) { delete ptr; size = obj.size; ptr = size? new int [size]: nullptr; memmove (ptr, obj.ptr, size* sizeof ( int )); return * this ; } } ~anyArrayClass() { delete [] ptr; } } |
上述赋值运算符执行以下操作: 1.自我分配检查。 2.如果分配给自己的不是自己,那么它会执行以下操作。 a) 释放分配给此->ptr的内存 b) 为该->ptr分配新内存并复制值 c) 归还这个
上述方法的缺点:
- 自我分配检查:自我分配很少进行,因此自我分配检查在大多数情况下都不相关。这只会减慢代码的速度。
- 内存释放和分配:可以看到,首先释放内存(让指针悬空),然后分配新的内存块。现在,如果由于某种原因,内存没有分配,并且抛出了一个异常,那么“this->ptr”将悬空指向一个释放的内存。场景应该是,要么分配成功,要么对象根本不应该被改变。
下面是复制和交换方法的作用。这种方法优雅地解决了上述问题,还提供了代码可重用性的范围。让我们看看到底是什么。
考虑下面的代码:
// Simple C++ program to demonstrate use of copy-and-swap // idiom by improving above code. #include <iostream> #include <cstring> using namespace std; class anyArrayClass { int size; int *ptr; public : anyArrayClass( int s=0):size(s), ptr(size? new int [size]:nullptr) {} // Copy constructor anyArrayClass( const anyArrayClass& obj):size(obj.size), ptr(size? new int [size]:nullptr) { memmove (ptr, obj.ptr, size* sizeof ( int )); } friend void swap(anyArrayClass& obj1, anyArrayClass& obj2) { std::swap(obj1.size, obj2.size); std::swap(obj1.ptr, obj2.ptr); } // overloaded assignment operator // argument passed by value. calls copy ctor anyArrayClass& operator=(anyArrayClass obj) { // calling friend function swap(* this , obj); return * this ; } ~anyArrayClass() { delete [] ptr; } } |
在上面的示例中,“operator=()”的参数由调用copy构造函数的值传递,以创建“operator=()”本地的anyArrayClass对象。然后将临时对象的值与“*this”对象交换(赋值运算符调用的LHS)。
优势:
- 由于参数是按值传递的,因此无需进行更多的自分配检查(这意味着无需进行更多内存释放)。此外,由于自分配非常罕见,因此在自分配的情况下复制的开销应该不是问题。
- 现在,由于复制构造函数用于创建临时对象,因此,只有在创建临时对象时,才会进行交换。基本上,我们在这里手工做的,是编译器在这里为我们做的。
- 代码可重用性:正如我们看到的那样,’operator=()’的主体中没有太多代码,我们使用复制构造函数和交换函数来完成这项工作。
本文由 比什瓦·纳特 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 贡献极客。组织 或者把你的文章寄到contribute@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。
如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END